@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
|
@@ -393,7 +393,7 @@ var RtThreadListComponent = class RtThreadListComponent {
|
|
|
393
393
|
}],
|
|
394
394
|
ngImport: i0,
|
|
395
395
|
template: "<ng-container rtBlock=\"rt-thread-list\">\n <header rtElem=\"head\">\n @if (searchTemplate()) {\n <div rtElem=\"search\" qa-dataid=\"thread-list-search\">\n <ng-container [ngTemplateOutlet]=\"searchTemplate()?.templateRef ?? null\" />\n </div>\n } @else {\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"thread-list-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchPlaceholderText()\"\n [formControl]=\"searchControl\" />\n }\n @if (filtersTemplate()) {\n <rt-icon-button\n rtElem=\"filter-trigger\"\n qa-dataid=\"thread-list-filter\"\n icon=\"filter\"\n variant=\"secondary\"\n rtPopoverAlign=\"end\"\n [ariaLabel]=\"t().uiFilters\"\n [indicator]=\"filtersActive()\"\n [rtPopover]=\"filtersPanel\" />\n }\n </header>\n\n <ng-template #rowButton let-row>\n <button\n rtElem=\"row\"\n qa-dataid=\"thread-list-row\"\n type=\"button\"\n [attr.data-id]=\"row.id\"\n [attr.data-unread]=\"row.hasUnread\"\n [attr.aria-current]=\"row.id === activeId() ? 'true' : null\"\n [rtMod]=\"{\n active: row.id === activeId(),\n unread: row.hasUnread,\n overdue: !!row.overdue,\n }\"\n (click)=\"onSelect(row.id, $event)\">\n @if (row.sign; as sign) {\n <rt-service-logo rtElem=\"row-sign\" qa-dataid=\"thread-list-row-sign\" size=\"xs\" [logos]=\"[sign]\" />\n <span rtElem=\"row-content\">\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </span>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n </button>\n </ng-template>\n\n <ng-template #rowContent let-row>\n <ng-container [ngTemplateOutlet]=\"rowTemplate()?.templateRef ?? null\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </ng-template>\n\n <ng-template #filtersPanel>\n <div rtElem=\"filters-panel\" qa-dataid=\"thread-list-filters-panel\">\n <ng-container [ngTemplateOutlet]=\"filtersTemplate()?.templateRef ?? null\" />\n </div>\n </ng-template>\n\n <div rtElem=\"rows\" qa-dataid=\"thread-list-rows\">\n @if (loading() && !rows().length) {\n @for (i of skeletonRows; track i) {\n <div rtElem=\"row-skeleton\" qa-dataid=\"thread-list-row-skeleton\" aria-hidden=\"true\">\n <rt-skeleton width=\"60%\" height=\"14px\" />\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n } @else if (!rows().length) {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"thread-list-empty\" [description]=\"t().uiThreadListEmptyHint\" [title]=\"emptyTitle()\">\n <div rtEmptyIllustration rtElem=\"empty-preview\">\n @for (row of emptyPreviewRows(); track row.id) {\n <div rtElem=\"empty-card\" [rtMod]=\"{ offset: row.offset }\">\n <span rtElem=\"empty-avatar\">\n <rt-icon size=\"sm\" [name]=\"row.icon\" />\n </span>\n <span rtElem=\"empty-lines\">\n <span rtElem=\"empty-line\" [rtMod]=\"{ short: true }\"></span>\n <span rtElem=\"empty-line\"></span>\n </span>\n </div>\n }\n </div>\n </rt-empty-state>\n } @else {\n @for (row of rows(); track row.id) {\n @if (rowActionsTemplate(); as actions) {\n <div rtElem=\"row-wrap\" qa-dataid=\"thread-list-row-wrap\">\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n <div rtElem=\"row-actions\" qa-dataid=\"thread-list-row-actions\">\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </div>\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n }\n @if (fetching()) {\n <div rtElem=\"row-loader\" qa-dataid=\"thread-list-row-loader\">\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n @if (hasMore()) {\n <div\n rtElem=\"load-anchor\"\n qa-dataid=\"thread-list-load-more\"\n aria-hidden=\"true\"\n rtInfiniteScroll\n [disabled]=\"fetching()\"\n (loadMore)=\"onLoadMore()\"></div>\n }\n }\n </div>\n</ng-container>\n",
|
|
396
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-thread-list{--rt-thread-list-border-width: var(--rt-border-width-thin);--rt-thread-list-card-radius: var(--rt-radius-lg);--rt-thread-list-tag-radius: var(--rt-radius-sm);--rt-thread-list-dot-radius: var(--rt-radius-full);--rt-thread-list-avatar-radius: var(--rt-radius-full);--rt-thread-list-line-radius: var(--rt-radius-full);display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.rt-thread-list__head{display:flex;flex:0 0 auto;align-items:center;block-size:56px;border-block-end:var(--rt-thread-list-border-width) solid var(--rt-color-border-strong);gap:var(--rt-space-2);padding-inline:var(--rt-space-4)}.rt-thread-list__search{flex:1 1 auto;min-inline-size:0}.rt-thread-list__filter-trigger{flex:0 0 auto}.rt-thread-list__filters-panel{display:flex;flex-direction:column;padding:var(--rt-space-4);gap:var(--rt-space-2);min-inline-size:220px}.rt-thread-list__rows{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;overflow-y:auto}.rt-thread-list__row{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4);border:none;background:none;border-inline-start:3px solid transparent;cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);gap:var(--rt-space-4);inline-size:100%;text-align:start}.rt-thread-list__row:hover{background:var(--rt-color-bg-subtle)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread{position:relative;background:var(--rt-color-bg-subtle);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread .rt-thread-list__row-title{font-weight:var(--rt-font-weight-semibold)}.rt-thread-list__row--unread:before{position:absolute;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-action-primary);block-size:var(--rt-space-2);content:\"\";inline-size:var(--rt-space-2);inset-block-start:50%;inset-inline-start:var(--rt-space-2);transform:translateY(-50%)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg)}.rt-thread-list__row--overdue .rt-thread-list__row-time{color:var(--rt-color-state-error-text)}.rt-thread-list__row-wrap{position:relative}.rt-thread-list__row-
|
|
396
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-thread-list{--rt-thread-list-border-width: var(--rt-border-width-thin);--rt-thread-list-card-radius: var(--rt-radius-lg);--rt-thread-list-tag-radius: var(--rt-radius-sm);--rt-thread-list-dot-radius: var(--rt-radius-full);--rt-thread-list-avatar-radius: var(--rt-radius-full);--rt-thread-list-line-radius: var(--rt-radius-full);display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.rt-thread-list__head{display:flex;flex:0 0 auto;align-items:center;block-size:56px;border-block-end:var(--rt-thread-list-border-width) solid var(--rt-color-border-strong);gap:var(--rt-space-2);padding-inline:var(--rt-space-4)}.rt-thread-list__search{flex:1 1 auto;min-inline-size:0}.rt-thread-list__filter-trigger{flex:0 0 auto}.rt-thread-list__filters-panel{display:flex;flex-direction:column;padding:var(--rt-space-4);gap:var(--rt-space-2);min-inline-size:220px}.rt-thread-list__rows{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;overflow-y:auto;overscroll-behavior:contain}.rt-thread-list__row{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4);border:none;background:none;border-inline-start:3px solid transparent;cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);gap:var(--rt-space-4);inline-size:100%;text-align:start}.rt-thread-list__row:hover{background:var(--rt-color-bg-subtle)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread{position:relative;background:var(--rt-color-bg-subtle);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread .rt-thread-list__row-title{font-weight:var(--rt-font-weight-semibold)}.rt-thread-list__row--unread:before{position:absolute;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-action-primary);block-size:var(--rt-space-2);content:\"\";inline-size:var(--rt-space-2);inset-block-start:50%;inset-inline-start:var(--rt-space-2);transform:translateY(-50%)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg)}.rt-thread-list__row--overdue .rt-thread-list__row-time{color:var(--rt-color-state-error-text)}.rt-thread-list__row-wrap{position:relative}.rt-thread-list__row-actions{position:absolute;display:flex;align-items:center;background:var(--rt-color-bg-subtle);gap:var(--rt-space-1);inset-block:0;inset-inline-end:0;padding-inline:var(--rt-space-2) var(--rt-space-4)}@media(hover:hover){.rt-thread-list__row-actions{opacity:0;pointer-events:none}.rt-thread-list__row-wrap:hover .rt-thread-list__row-actions,.rt-thread-list__row-wrap:focus-within .rt-thread-list__row-actions,.rt-thread-list__row-wrap:has(.rt-menu--open) .rt-thread-list__row-actions{opacity:1;pointer-events:auto}}.rt-thread-list__row--active+.rt-thread-list__row-actions{background:var(--rt-color-state-info-bg)}.rt-thread-list__row-sign{flex:none}.rt-thread-list__row-content{display:flex;flex:1 1 auto;align-items:center;justify-content:space-between;gap:var(--rt-space-4);min-inline-size:0}.rt-thread-list__row-body{display:flex;flex-direction:column;gap:var(--rt-space-0-5);min-inline-size:0}.rt-thread-list__row-title{overflow:hidden;color:var(--rt-color-text-primary);text-overflow:ellipsis;white-space:nowrap}.rt-thread-list__row-id{color:var(--rt-color-text-muted);font-size:var(--rt-text-sm)}.rt-thread-list__row:hover .rt-copy-cell__button,.rt-thread-list__row:focus-within .rt-copy-cell__button{opacity:1}.rt-thread-list__row-subtitle{overflow:hidden;color:var(--rt-color-text-muted);text-overflow:ellipsis;white-space:nowrap}.rt-thread-list__row-meta{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-space-2)}.rt-thread-list__row-time{color:var(--rt-color-text-muted);white-space:nowrap}.rt-thread-list__row-tag{padding:var(--rt-space-0-5) var(--rt-space-2);border-radius:var(--rt-thread-list-tag-radius);background:var(--rt-color-state-warning-bg);color:var(--rt-color-state-warning-text);font-size:var(--rt-text-xs);white-space:nowrap}.rt-thread-list__row-dot{display:inline-block;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-text-link);block-size:6px;inline-size:6px}.rt-thread-list__row-skeleton{display:flex;flex-direction:column;padding:var(--rt-space-2) var(--rt-space-4);gap:var(--rt-space-2)}.rt-thread-list__row-loader{display:flex;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4)}.rt-thread-list__load-anchor{block-size:1px}.rt-thread-list__empty{padding:var(--rt-space-6) var(--rt-space-4)}.rt-thread-list__empty-preview{display:flex;flex-direction:column;gap:var(--rt-space-1)}.rt-thread-list__empty-card{display:flex;align-items:center;padding:var(--rt-space-2);border:var(--rt-thread-list-border-width) solid var(--rt-color-border-subtle);border-radius:var(--rt-thread-list-card-radius);background:var(--rt-color-bg-surface-subtle);gap:var(--rt-space-2)}.rt-thread-list__empty-card--offset{transform:translate(20px)}.rt-thread-list__empty-avatar{display:grid;flex:0 0 auto;border-radius:var(--rt-thread-list-avatar-radius);background:var(--rt-color-text-muted);block-size:24px;color:var(--rt-color-bg-surface);inline-size:24px;place-items:center}.rt-thread-list__empty-lines{display:flex;flex-direction:column;gap:var(--rt-space-2)}.rt-thread-list__empty-line{border-radius:var(--rt-thread-list-line-radius);background:var(--rt-color-border-strong);block-size:6px;inline-size:112px}.rt-thread-list__empty-line--short{inline-size:48px}.rt-thread-list[data-rt-radius=none]{--rt-thread-list-card-radius: var(--rt-radius-none)}.rt-thread-list[data-rt-radius=xs]{--rt-thread-list-card-radius: var(--rt-radius-xs)}.rt-thread-list[data-rt-radius=sm]{--rt-thread-list-card-radius: var(--rt-radius-sm)}.rt-thread-list[data-rt-radius=ms]{--rt-thread-list-card-radius: var(--rt-radius-ms)}.rt-thread-list[data-rt-radius=md]{--rt-thread-list-card-radius: var(--rt-radius-md)}.rt-thread-list[data-rt-radius=lg]{--rt-thread-list-card-radius: var(--rt-radius-lg)}.rt-thread-list[data-rt-radius=xl]{--rt-thread-list-card-radius: var(--rt-radius-xl)}.rt-thread-list[data-rt-radius=\"2xl\"]{--rt-thread-list-card-radius: var(--rt-radius-2xl)}.rt-thread-list[data-rt-radius=full]{--rt-thread-list-card-radius: var(--rt-radius-full)}}\n"],
|
|
397
397
|
dependencies: [
|
|
398
398
|
{
|
|
399
399
|
kind: "directive",
|
|
@@ -603,7 +603,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
603
603
|
}],
|
|
604
604
|
host: { class: BEM_BLOCK },
|
|
605
605
|
template: "<ng-container rtBlock=\"rt-thread-list\">\n <header rtElem=\"head\">\n @if (searchTemplate()) {\n <div rtElem=\"search\" qa-dataid=\"thread-list-search\">\n <ng-container [ngTemplateOutlet]=\"searchTemplate()?.templateRef ?? null\" />\n </div>\n } @else {\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"thread-list-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchPlaceholderText()\"\n [formControl]=\"searchControl\" />\n }\n @if (filtersTemplate()) {\n <rt-icon-button\n rtElem=\"filter-trigger\"\n qa-dataid=\"thread-list-filter\"\n icon=\"filter\"\n variant=\"secondary\"\n rtPopoverAlign=\"end\"\n [ariaLabel]=\"t().uiFilters\"\n [indicator]=\"filtersActive()\"\n [rtPopover]=\"filtersPanel\" />\n }\n </header>\n\n <ng-template #rowButton let-row>\n <button\n rtElem=\"row\"\n qa-dataid=\"thread-list-row\"\n type=\"button\"\n [attr.data-id]=\"row.id\"\n [attr.data-unread]=\"row.hasUnread\"\n [attr.aria-current]=\"row.id === activeId() ? 'true' : null\"\n [rtMod]=\"{\n active: row.id === activeId(),\n unread: row.hasUnread,\n overdue: !!row.overdue,\n }\"\n (click)=\"onSelect(row.id, $event)\">\n @if (row.sign; as sign) {\n <rt-service-logo rtElem=\"row-sign\" qa-dataid=\"thread-list-row-sign\" size=\"xs\" [logos]=\"[sign]\" />\n <span rtElem=\"row-content\">\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </span>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n </button>\n </ng-template>\n\n <ng-template #rowContent let-row>\n <ng-container [ngTemplateOutlet]=\"rowTemplate()?.templateRef ?? null\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </ng-template>\n\n <ng-template #filtersPanel>\n <div rtElem=\"filters-panel\" qa-dataid=\"thread-list-filters-panel\">\n <ng-container [ngTemplateOutlet]=\"filtersTemplate()?.templateRef ?? null\" />\n </div>\n </ng-template>\n\n <div rtElem=\"rows\" qa-dataid=\"thread-list-rows\">\n @if (loading() && !rows().length) {\n @for (i of skeletonRows; track i) {\n <div rtElem=\"row-skeleton\" qa-dataid=\"thread-list-row-skeleton\" aria-hidden=\"true\">\n <rt-skeleton width=\"60%\" height=\"14px\" />\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n } @else if (!rows().length) {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"thread-list-empty\" [description]=\"t().uiThreadListEmptyHint\" [title]=\"emptyTitle()\">\n <div rtEmptyIllustration rtElem=\"empty-preview\">\n @for (row of emptyPreviewRows(); track row.id) {\n <div rtElem=\"empty-card\" [rtMod]=\"{ offset: row.offset }\">\n <span rtElem=\"empty-avatar\">\n <rt-icon size=\"sm\" [name]=\"row.icon\" />\n </span>\n <span rtElem=\"empty-lines\">\n <span rtElem=\"empty-line\" [rtMod]=\"{ short: true }\"></span>\n <span rtElem=\"empty-line\"></span>\n </span>\n </div>\n }\n </div>\n </rt-empty-state>\n } @else {\n @for (row of rows(); track row.id) {\n @if (rowActionsTemplate(); as actions) {\n <div rtElem=\"row-wrap\" qa-dataid=\"thread-list-row-wrap\">\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n <div rtElem=\"row-actions\" qa-dataid=\"thread-list-row-actions\">\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </div>\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n }\n @if (fetching()) {\n <div rtElem=\"row-loader\" qa-dataid=\"thread-list-row-loader\">\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n @if (hasMore()) {\n <div\n rtElem=\"load-anchor\"\n qa-dataid=\"thread-list-load-more\"\n aria-hidden=\"true\"\n rtInfiniteScroll\n [disabled]=\"fetching()\"\n (loadMore)=\"onLoadMore()\"></div>\n }\n }\n </div>\n</ng-container>\n",
|
|
606
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-thread-list{--rt-thread-list-border-width: var(--rt-border-width-thin);--rt-thread-list-card-radius: var(--rt-radius-lg);--rt-thread-list-tag-radius: var(--rt-radius-sm);--rt-thread-list-dot-radius: var(--rt-radius-full);--rt-thread-list-avatar-radius: var(--rt-radius-full);--rt-thread-list-line-radius: var(--rt-radius-full);display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.rt-thread-list__head{display:flex;flex:0 0 auto;align-items:center;block-size:56px;border-block-end:var(--rt-thread-list-border-width) solid var(--rt-color-border-strong);gap:var(--rt-space-2);padding-inline:var(--rt-space-4)}.rt-thread-list__search{flex:1 1 auto;min-inline-size:0}.rt-thread-list__filter-trigger{flex:0 0 auto}.rt-thread-list__filters-panel{display:flex;flex-direction:column;padding:var(--rt-space-4);gap:var(--rt-space-2);min-inline-size:220px}.rt-thread-list__rows{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;overflow-y:auto}.rt-thread-list__row{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4);border:none;background:none;border-inline-start:3px solid transparent;cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);gap:var(--rt-space-4);inline-size:100%;text-align:start}.rt-thread-list__row:hover{background:var(--rt-color-bg-subtle)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread{position:relative;background:var(--rt-color-bg-subtle);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread .rt-thread-list__row-title{font-weight:var(--rt-font-weight-semibold)}.rt-thread-list__row--unread:before{position:absolute;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-action-primary);block-size:var(--rt-space-2);content:\"\";inline-size:var(--rt-space-2);inset-block-start:50%;inset-inline-start:var(--rt-space-2);transform:translateY(-50%)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg)}.rt-thread-list__row--overdue .rt-thread-list__row-time{color:var(--rt-color-state-error-text)}.rt-thread-list__row-wrap{position:relative}.rt-thread-list__row-
|
|
606
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-thread-list{--rt-thread-list-border-width: var(--rt-border-width-thin);--rt-thread-list-card-radius: var(--rt-radius-lg);--rt-thread-list-tag-radius: var(--rt-radius-sm);--rt-thread-list-dot-radius: var(--rt-radius-full);--rt-thread-list-avatar-radius: var(--rt-radius-full);--rt-thread-list-line-radius: var(--rt-radius-full);display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0}.rt-thread-list__head{display:flex;flex:0 0 auto;align-items:center;block-size:56px;border-block-end:var(--rt-thread-list-border-width) solid var(--rt-color-border-strong);gap:var(--rt-space-2);padding-inline:var(--rt-space-4)}.rt-thread-list__search{flex:1 1 auto;min-inline-size:0}.rt-thread-list__filter-trigger{flex:0 0 auto}.rt-thread-list__filters-panel{display:flex;flex-direction:column;padding:var(--rt-space-4);gap:var(--rt-space-2);min-inline-size:220px}.rt-thread-list__rows{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;overflow-y:auto;overscroll-behavior:contain}.rt-thread-list__row{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4);border:none;background:none;border-inline-start:3px solid transparent;cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);gap:var(--rt-space-4);inline-size:100%;text-align:start}.rt-thread-list__row:hover{background:var(--rt-color-bg-subtle)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread{position:relative;background:var(--rt-color-bg-subtle);border-inline-start-color:var(--rt-color-action-primary)}.rt-thread-list__row--unread .rt-thread-list__row-title{font-weight:var(--rt-font-weight-semibold)}.rt-thread-list__row--unread:before{position:absolute;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-action-primary);block-size:var(--rt-space-2);content:\"\";inline-size:var(--rt-space-2);inset-block-start:50%;inset-inline-start:var(--rt-space-2);transform:translateY(-50%)}.rt-thread-list__row--active,.rt-thread-list__row--active:hover{background:var(--rt-color-state-info-bg)}.rt-thread-list__row--overdue .rt-thread-list__row-time{color:var(--rt-color-state-error-text)}.rt-thread-list__row-wrap{position:relative}.rt-thread-list__row-actions{position:absolute;display:flex;align-items:center;background:var(--rt-color-bg-subtle);gap:var(--rt-space-1);inset-block:0;inset-inline-end:0;padding-inline:var(--rt-space-2) var(--rt-space-4)}@media(hover:hover){.rt-thread-list__row-actions{opacity:0;pointer-events:none}.rt-thread-list__row-wrap:hover .rt-thread-list__row-actions,.rt-thread-list__row-wrap:focus-within .rt-thread-list__row-actions,.rt-thread-list__row-wrap:has(.rt-menu--open) .rt-thread-list__row-actions{opacity:1;pointer-events:auto}}.rt-thread-list__row--active+.rt-thread-list__row-actions{background:var(--rt-color-state-info-bg)}.rt-thread-list__row-sign{flex:none}.rt-thread-list__row-content{display:flex;flex:1 1 auto;align-items:center;justify-content:space-between;gap:var(--rt-space-4);min-inline-size:0}.rt-thread-list__row-body{display:flex;flex-direction:column;gap:var(--rt-space-0-5);min-inline-size:0}.rt-thread-list__row-title{overflow:hidden;color:var(--rt-color-text-primary);text-overflow:ellipsis;white-space:nowrap}.rt-thread-list__row-id{color:var(--rt-color-text-muted);font-size:var(--rt-text-sm)}.rt-thread-list__row:hover .rt-copy-cell__button,.rt-thread-list__row:focus-within .rt-copy-cell__button{opacity:1}.rt-thread-list__row-subtitle{overflow:hidden;color:var(--rt-color-text-muted);text-overflow:ellipsis;white-space:nowrap}.rt-thread-list__row-meta{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-space-2)}.rt-thread-list__row-time{color:var(--rt-color-text-muted);white-space:nowrap}.rt-thread-list__row-tag{padding:var(--rt-space-0-5) var(--rt-space-2);border-radius:var(--rt-thread-list-tag-radius);background:var(--rt-color-state-warning-bg);color:var(--rt-color-state-warning-text);font-size:var(--rt-text-xs);white-space:nowrap}.rt-thread-list__row-dot{display:inline-block;border-radius:var(--rt-thread-list-dot-radius);background:var(--rt-color-text-link);block-size:6px;inline-size:6px}.rt-thread-list__row-skeleton{display:flex;flex-direction:column;padding:var(--rt-space-2) var(--rt-space-4);gap:var(--rt-space-2)}.rt-thread-list__row-loader{display:flex;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4)}.rt-thread-list__load-anchor{block-size:1px}.rt-thread-list__empty{padding:var(--rt-space-6) var(--rt-space-4)}.rt-thread-list__empty-preview{display:flex;flex-direction:column;gap:var(--rt-space-1)}.rt-thread-list__empty-card{display:flex;align-items:center;padding:var(--rt-space-2);border:var(--rt-thread-list-border-width) solid var(--rt-color-border-subtle);border-radius:var(--rt-thread-list-card-radius);background:var(--rt-color-bg-surface-subtle);gap:var(--rt-space-2)}.rt-thread-list__empty-card--offset{transform:translate(20px)}.rt-thread-list__empty-avatar{display:grid;flex:0 0 auto;border-radius:var(--rt-thread-list-avatar-radius);background:var(--rt-color-text-muted);block-size:24px;color:var(--rt-color-bg-surface);inline-size:24px;place-items:center}.rt-thread-list__empty-lines{display:flex;flex-direction:column;gap:var(--rt-space-2)}.rt-thread-list__empty-line{border-radius:var(--rt-thread-list-line-radius);background:var(--rt-color-border-strong);block-size:6px;inline-size:112px}.rt-thread-list__empty-line--short{inline-size:48px}.rt-thread-list[data-rt-radius=none]{--rt-thread-list-card-radius: var(--rt-radius-none)}.rt-thread-list[data-rt-radius=xs]{--rt-thread-list-card-radius: var(--rt-radius-xs)}.rt-thread-list[data-rt-radius=sm]{--rt-thread-list-card-radius: var(--rt-radius-sm)}.rt-thread-list[data-rt-radius=ms]{--rt-thread-list-card-radius: var(--rt-radius-ms)}.rt-thread-list[data-rt-radius=md]{--rt-thread-list-card-radius: var(--rt-radius-md)}.rt-thread-list[data-rt-radius=lg]{--rt-thread-list-card-radius: var(--rt-radius-lg)}.rt-thread-list[data-rt-radius=xl]{--rt-thread-list-card-radius: var(--rt-radius-xl)}.rt-thread-list[data-rt-radius=\"2xl\"]{--rt-thread-list-card-radius: var(--rt-radius-2xl)}.rt-thread-list[data-rt-radius=full]{--rt-thread-list-card-radius: var(--rt-radius-full)}}\n"]
|
|
607
607
|
}]
|
|
608
608
|
}],
|
|
609
609
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-thread-list.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.directives.ts","../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.component.ts","../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.component.html"],"sourcesContent":["import { Directive, inject, input, InputSignal, TemplateRef } from '@angular/core';\n\nimport { IRtThreadList } from './rt-thread-list.model';\n\n/**\n * Помечает `<ng-template>` содержимого строки списка. Входом `[rtThreadListRow]`\n * потребитель передаёт свой массив строк — из него выводится тип `TRow`, поэтому\n * `let-row` в темплейте типизируется строго (context-guard ниже это подтверждает).\n */\n@Directive({\n selector: 'ng-template[rtThreadListRow]',\n})\nexport class RtThreadListRowDirective<TRow extends IRtThreadList.Row> {\n public readonly templateRef: TemplateRef<IRtThreadList.RowContext<TRow>> =\n inject<TemplateRef<IRtThreadList.RowContext<TRow>>>(TemplateRef);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([], {\n alias: 'rtThreadListRow',\n });\n\n public static ngTemplateContextGuard<TRow extends IRtThreadList.Row>(\n _directive: RtThreadListRowDirective<TRow>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n context: unknown\n ): context is IRtThreadList.RowContext<TRow> {\n return true;\n }\n}\n\n/**\n * Помечает `<ng-template>` действий строки (удалить, закрепить). Действия рисуются рядом с\n * кнопкой строки, а не внутри неё: вложенная кнопка в `<button>` недопустима и крадёт клик\n * выбора строки. Видны при наведении и фокусе внутри строки.\n */\n@Directive({\n selector: 'ng-template[rtThreadListRowActions]',\n})\nexport class RtThreadListRowActionsDirective<TRow extends IRtThreadList.Row> {\n public readonly templateRef: TemplateRef<IRtThreadList.RowContext<TRow>> =\n inject<TemplateRef<IRtThreadList.RowContext<TRow>>>(TemplateRef);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([], {\n alias: 'rtThreadListRowActions',\n });\n\n public static ngTemplateContextGuard<TRow extends IRtThreadList.Row>(\n _directive: RtThreadListRowActionsDirective<TRow>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n context: unknown\n ): context is IRtThreadList.RowContext<TRow> {\n return true;\n }\n}\n\n/**\n * Помечает `<ng-template>` с фильтрами — его содержимое рендерится в поповере,\n * который открывает иконка-фильтр в шапке списка.\n */\n@Directive({\n selector: 'ng-template[rtThreadListFilters]',\n})\nexport class RtThreadListFiltersDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Помечает `<ng-template>` с кастомным контролом поиска. Когда потребитель его\n * проецирует, шапка списка рендерит его содержимое вместо встроенного `rt-input`\n * — так воркспейс подставляет свой автокомплит по каталогу вместо текстового\n * поиска, не ломая generic-природу списка.\n */\n@Directive({\n selector: 'ng-template[rtThreadListSearch]',\n})\nexport class RtThreadListSearchDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n contentChild,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n InputSignal,\n InputSignalWithTransform,\n OnInit,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormControl, ReactiveFormsModule } from '@angular/forms';\n\nimport { distinctUntilChanged, map } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { searchDebounce } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtInfiniteScrollDirective } from '@rt-tools/ui-kit-v2/core';\nimport { RtEmptyStateComponent } from '@rt-tools/ui-kit-v2/empty-state';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtInputComponent } from '@rt-tools/ui-kit-v2/input';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtServiceLogoComponent } from '@rt-tools/ui-kit-v2/service-logo';\nimport { RtSkeletonComponent } from '@rt-tools/ui-kit-v2/skeleton';\nimport {\n RtThreadListFiltersDirective,\n RtThreadListRowActionsDirective,\n RtThreadListRowDirective,\n RtThreadListSearchDirective,\n} from './rt-thread-list.directives';\nimport { IRtThreadList } from './rt-thread-list.model';\n\nconst BEM_BLOCK: string = 'rt-thread-list';\n\n/** Кол-во скелетон-строк на первичной загрузке (пока `rows` пусты). */\nconst SKELETON_ROWS_COUNT: number = 6;\n\n/** Значки строк-превью пустого списка по умолчанию: люди переписки. */\nconst PREVIEW_ICONS: readonly IRtIcon.Name[] = ['user', 'users', 'user'];\n\n/**\n * Презентационный список тредов для воркспейсов:\n * поиск с дебаунсом, фильтр-поповер и бесконечная прокрутка. Данные и оркестрация\n * — на вызывающем; список стора/api не видит.\n *\n * Строку рисует потребитель через `<ng-template rtThreadListRow let-row>` (body +\n * meta); оболочка владеет кнопкой строки (active/unread/overdue), поиском, кнопкой\n * фильтров (точка-индикатор при `filtersActive`) и скроллом. Фильтры потребитель\n * кладёт в `<ng-template rtThreadListFilters>` — они рендерятся в поповере.\n */\n@Component({\n selector: 'rt-thread-list',\n templateUrl: './rt-thread-list.component.html',\n styleUrls: ['./rt-thread-list.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n ReactiveFormsModule,\n\n // standalone components / directives\n RtEmptyStateComponent,\n RtIconComponent,\n RtIconButtonComponent,\n RtInputComponent,\n RtPopoverDirective,\n RtServiceLogoComponent,\n RtSkeletonComponent,\n BlockDirective,\n ElemDirective,\n RtInfiniteScrollDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtThreadListComponent<TRow extends IRtThreadList.Row> implements OnInit {\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #t_uiSearch: Signal<string> = rtKitLabel('uiSearch');\n readonly #t_uiNothingFound: Signal<string> = rtKitLabel('uiNothingFound');\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly searchPlaceholderText: Signal<string> = computed((): string => this.searchPlaceholder() || this.#t_uiSearch());\n protected readonly emptyTitle: Signal<string> = computed((): string => this.emptyText() || this.#t_uiNothingFound());\n\n protected readonly skeletonRows: number[] = Array.from({ length: SKELETON_ROWS_COUNT }, (_: unknown, i: number): number => i);\n\n /** Декоративные строки-превью пустого состояния: значок строки из `emptyPreviewIcons`, каждая вторая сдвинута. */\n protected readonly emptyPreviewRows: Signal<readonly IRtThreadList.PreviewRow[]> = computed((): readonly IRtThreadList.PreviewRow[] =>\n this.emptyPreviewIcons().map((icon: IRtIcon.Name, index: number): IRtThreadList.PreviewRow => ({\n icon,\n id: index,\n offset: index % 2 === 1,\n }))\n );\n\n protected readonly searchControl: FormControl<string> = new FormControl<string>('', {\n nonNullable: true,\n });\n\n protected readonly rowTemplate: Signal<RtThreadListRowDirective<TRow> | undefined> = contentChild(RtThreadListRowDirective<TRow>);\n\n protected readonly rowActionsTemplate: Signal<RtThreadListRowActionsDirective<TRow> | undefined> = contentChild(\n RtThreadListRowActionsDirective<TRow>\n );\n\n protected readonly filtersTemplate: Signal<RtThreadListFiltersDirective | undefined> = contentChild(RtThreadListFiltersDirective);\n\n protected readonly searchTemplate: Signal<RtThreadListSearchDirective | undefined> = contentChild(RtThreadListSearchDirective);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([]);\n\n public readonly activeId: InputSignal<IRtThreadList.TRowId | null> = input<IRtThreadList.TRowId | null>(null);\n\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly searchPlaceholder: InputSignal<string> = input<string>('');\n\n public readonly emptyText: InputSignal<string> = input<string>('');\n\n /** Значки декоративных строк-превью пустого состояния, по строке на значок */\n public readonly emptyPreviewIcons: InputSignal<readonly IRtIcon.Name[]> = input<readonly IRtIcon.Name[]>(PREVIEW_ICONS);\n\n public readonly loading: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly fetching: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly hasMore: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly filtersActive: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n // Имя `select` зарезервировано под нативное DOM-событие\n // (@angular-eslint/no-output-native), поэтому output переименован.\n public readonly selectRow: OutputEmitterRef<IRtThreadList.TRowId> = output<IRtThreadList.TRowId>();\n\n // Ctrl/⌘+клик по строке: потребитель открывает строку в новой вкладке.\n // Обычный клик остаётся на `selectRow`.\n public readonly openInNewTab: OutputEmitterRef<IRtThreadList.TRowId> = output<IRtThreadList.TRowId>();\n\n public readonly searchChange: OutputEmitterRef<string> = output<string>();\n\n public readonly loadMore: OutputEmitterRef<void> = output<void>();\n\n public ngOnInit(): void {\n // Дебаунс непустого ввода; очистка крестиком применяется сразу (searchDebounce).\n this.searchControl.valueChanges\n .pipe(\n map((value: string): string => value.trim()),\n searchDebounce(),\n distinctUntilChanged(),\n takeUntilDestroyed(this.#destroyRef)\n )\n .subscribe((value: string): void => this.searchChange.emit(value));\n }\n\n protected onSelect(id: IRtThreadList.TRowId, event: MouseEvent): void {\n // Ctrl (Win/Linux) или ⌘ (macOS) — «открыть в новой вкладке», как у\n // нативных ссылок. Иначе — обычный выбор строки в текущей вкладке.\n if (event.ctrlKey || event.metaKey) {\n this.openInNewTab.emit(id);\n return;\n }\n this.selectRow.emit(id);\n }\n\n protected onLoadMore(): void {\n this.loadMore.emit();\n }\n}\n","<ng-container rtBlock=\"rt-thread-list\">\n <header rtElem=\"head\">\n @if (searchTemplate()) {\n <div rtElem=\"search\" qa-dataid=\"thread-list-search\">\n <ng-container [ngTemplateOutlet]=\"searchTemplate()?.templateRef ?? null\" />\n </div>\n } @else {\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"thread-list-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchPlaceholderText()\"\n [formControl]=\"searchControl\" />\n }\n @if (filtersTemplate()) {\n <rt-icon-button\n rtElem=\"filter-trigger\"\n qa-dataid=\"thread-list-filter\"\n icon=\"filter\"\n variant=\"secondary\"\n rtPopoverAlign=\"end\"\n [ariaLabel]=\"t().uiFilters\"\n [indicator]=\"filtersActive()\"\n [rtPopover]=\"filtersPanel\" />\n }\n </header>\n\n <ng-template #rowButton let-row>\n <button\n rtElem=\"row\"\n qa-dataid=\"thread-list-row\"\n type=\"button\"\n [attr.data-id]=\"row.id\"\n [attr.data-unread]=\"row.hasUnread\"\n [attr.aria-current]=\"row.id === activeId() ? 'true' : null\"\n [rtMod]=\"{\n active: row.id === activeId(),\n unread: row.hasUnread,\n overdue: !!row.overdue,\n }\"\n (click)=\"onSelect(row.id, $event)\">\n @if (row.sign; as sign) {\n <rt-service-logo rtElem=\"row-sign\" qa-dataid=\"thread-list-row-sign\" size=\"xs\" [logos]=\"[sign]\" />\n <span rtElem=\"row-content\">\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </span>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n </button>\n </ng-template>\n\n <ng-template #rowContent let-row>\n <ng-container [ngTemplateOutlet]=\"rowTemplate()?.templateRef ?? null\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </ng-template>\n\n <ng-template #filtersPanel>\n <div rtElem=\"filters-panel\" qa-dataid=\"thread-list-filters-panel\">\n <ng-container [ngTemplateOutlet]=\"filtersTemplate()?.templateRef ?? null\" />\n </div>\n </ng-template>\n\n <div rtElem=\"rows\" qa-dataid=\"thread-list-rows\">\n @if (loading() && !rows().length) {\n @for (i of skeletonRows; track i) {\n <div rtElem=\"row-skeleton\" qa-dataid=\"thread-list-row-skeleton\" aria-hidden=\"true\">\n <rt-skeleton width=\"60%\" height=\"14px\" />\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n } @else if (!rows().length) {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"thread-list-empty\" [description]=\"t().uiThreadListEmptyHint\" [title]=\"emptyTitle()\">\n <div rtEmptyIllustration rtElem=\"empty-preview\">\n @for (row of emptyPreviewRows(); track row.id) {\n <div rtElem=\"empty-card\" [rtMod]=\"{ offset: row.offset }\">\n <span rtElem=\"empty-avatar\">\n <rt-icon size=\"sm\" [name]=\"row.icon\" />\n </span>\n <span rtElem=\"empty-lines\">\n <span rtElem=\"empty-line\" [rtMod]=\"{ short: true }\"></span>\n <span rtElem=\"empty-line\"></span>\n </span>\n </div>\n }\n </div>\n </rt-empty-state>\n } @else {\n @for (row of rows(); track row.id) {\n @if (rowActionsTemplate(); as actions) {\n <div rtElem=\"row-wrap\" qa-dataid=\"thread-list-row-wrap\">\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n <div rtElem=\"row-actions\" qa-dataid=\"thread-list-row-actions\">\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </div>\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n }\n @if (fetching()) {\n <div rtElem=\"row-loader\" qa-dataid=\"thread-list-row-loader\">\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n @if (hasMore()) {\n <div\n rtElem=\"load-anchor\"\n qa-dataid=\"thread-list-load-more\"\n aria-hidden=\"true\"\n rtInfiniteScroll\n [disabled]=\"fetching()\"\n (loadMore)=\"onLoadMore()\"></div>\n }\n }\n </div>\n</ng-container>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-thread-list.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.directives.ts","../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.component.ts","../../../projects/ui-kit-v2/src/lib/components/thread-list/rt-thread-list.component.html"],"sourcesContent":["import { Directive, inject, input, InputSignal, TemplateRef } from '@angular/core';\n\nimport { IRtThreadList } from './rt-thread-list.model';\n\n/**\n * Помечает `<ng-template>` содержимого строки списка. Входом `[rtThreadListRow]`\n * потребитель передаёт свой массив строк — из него выводится тип `TRow`, поэтому\n * `let-row` в темплейте типизируется строго (context-guard ниже это подтверждает).\n */\n@Directive({\n selector: 'ng-template[rtThreadListRow]',\n})\nexport class RtThreadListRowDirective<TRow extends IRtThreadList.Row> {\n public readonly templateRef: TemplateRef<IRtThreadList.RowContext<TRow>> =\n inject<TemplateRef<IRtThreadList.RowContext<TRow>>>(TemplateRef);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([], {\n alias: 'rtThreadListRow',\n });\n\n public static ngTemplateContextGuard<TRow extends IRtThreadList.Row>(\n _directive: RtThreadListRowDirective<TRow>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n context: unknown\n ): context is IRtThreadList.RowContext<TRow> {\n return true;\n }\n}\n\n/**\n * Помечает `<ng-template>` действий строки (удалить, закрепить). Действия рисуются рядом с\n * кнопкой строки, а не внутри неё: вложенная кнопка в `<button>` недопустима и крадёт клик\n * выбора строки. Видны при наведении и фокусе внутри строки.\n */\n@Directive({\n selector: 'ng-template[rtThreadListRowActions]',\n})\nexport class RtThreadListRowActionsDirective<TRow extends IRtThreadList.Row> {\n public readonly templateRef: TemplateRef<IRtThreadList.RowContext<TRow>> =\n inject<TemplateRef<IRtThreadList.RowContext<TRow>>>(TemplateRef);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([], {\n alias: 'rtThreadListRowActions',\n });\n\n public static ngTemplateContextGuard<TRow extends IRtThreadList.Row>(\n _directive: RtThreadListRowActionsDirective<TRow>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n context: unknown\n ): context is IRtThreadList.RowContext<TRow> {\n return true;\n }\n}\n\n/**\n * Помечает `<ng-template>` с фильтрами — его содержимое рендерится в поповере,\n * который открывает иконка-фильтр в шапке списка.\n */\n@Directive({\n selector: 'ng-template[rtThreadListFilters]',\n})\nexport class RtThreadListFiltersDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n/**\n * Помечает `<ng-template>` с кастомным контролом поиска. Когда потребитель его\n * проецирует, шапка списка рендерит его содержимое вместо встроенного `rt-input`\n * — так воркспейс подставляет свой автокомплит по каталогу вместо текстового\n * поиска, не ломая generic-природу списка.\n */\n@Directive({\n selector: 'ng-template[rtThreadListSearch]',\n})\nexport class RtThreadListSearchDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n contentChild,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n InputSignal,\n InputSignalWithTransform,\n OnInit,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormControl, ReactiveFormsModule } from '@angular/forms';\n\nimport { distinctUntilChanged, map } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { searchDebounce } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtInfiniteScrollDirective } from '@rt-tools/ui-kit-v2/core';\nimport { RtEmptyStateComponent } from '@rt-tools/ui-kit-v2/empty-state';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtInputComponent } from '@rt-tools/ui-kit-v2/input';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtServiceLogoComponent } from '@rt-tools/ui-kit-v2/service-logo';\nimport { RtSkeletonComponent } from '@rt-tools/ui-kit-v2/skeleton';\nimport {\n RtThreadListFiltersDirective,\n RtThreadListRowActionsDirective,\n RtThreadListRowDirective,\n RtThreadListSearchDirective,\n} from './rt-thread-list.directives';\nimport { IRtThreadList } from './rt-thread-list.model';\n\nconst BEM_BLOCK: string = 'rt-thread-list';\n\n/** Кол-во скелетон-строк на первичной загрузке (пока `rows` пусты). */\nconst SKELETON_ROWS_COUNT: number = 6;\n\n/** Значки строк-превью пустого списка по умолчанию: люди переписки. */\nconst PREVIEW_ICONS: readonly IRtIcon.Name[] = ['user', 'users', 'user'];\n\n/**\n * Презентационный список тредов для воркспейсов:\n * поиск с дебаунсом, фильтр-поповер и бесконечная прокрутка. Данные и оркестрация\n * — на вызывающем; список стора/api не видит.\n *\n * Строку рисует потребитель через `<ng-template rtThreadListRow let-row>` (body +\n * meta); оболочка владеет кнопкой строки (active/unread/overdue), поиском, кнопкой\n * фильтров (точка-индикатор при `filtersActive`) и скроллом. Фильтры потребитель\n * кладёт в `<ng-template rtThreadListFilters>` — они рендерятся в поповере.\n */\n@Component({\n selector: 'rt-thread-list',\n templateUrl: './rt-thread-list.component.html',\n styleUrls: ['./rt-thread-list.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n ReactiveFormsModule,\n\n // standalone components / directives\n RtEmptyStateComponent,\n RtIconComponent,\n RtIconButtonComponent,\n RtInputComponent,\n RtPopoverDirective,\n RtServiceLogoComponent,\n RtSkeletonComponent,\n BlockDirective,\n ElemDirective,\n RtInfiniteScrollDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtThreadListComponent<TRow extends IRtThreadList.Row> implements OnInit {\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #t_uiSearch: Signal<string> = rtKitLabel('uiSearch');\n readonly #t_uiNothingFound: Signal<string> = rtKitLabel('uiNothingFound');\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly searchPlaceholderText: Signal<string> = computed((): string => this.searchPlaceholder() || this.#t_uiSearch());\n protected readonly emptyTitle: Signal<string> = computed((): string => this.emptyText() || this.#t_uiNothingFound());\n\n protected readonly skeletonRows: number[] = Array.from({ length: SKELETON_ROWS_COUNT }, (_: unknown, i: number): number => i);\n\n /** Декоративные строки-превью пустого состояния: значок строки из `emptyPreviewIcons`, каждая вторая сдвинута. */\n protected readonly emptyPreviewRows: Signal<readonly IRtThreadList.PreviewRow[]> = computed((): readonly IRtThreadList.PreviewRow[] =>\n this.emptyPreviewIcons().map((icon: IRtIcon.Name, index: number): IRtThreadList.PreviewRow => ({\n icon,\n id: index,\n offset: index % 2 === 1,\n }))\n );\n\n protected readonly searchControl: FormControl<string> = new FormControl<string>('', {\n nonNullable: true,\n });\n\n protected readonly rowTemplate: Signal<RtThreadListRowDirective<TRow> | undefined> = contentChild(RtThreadListRowDirective<TRow>);\n\n protected readonly rowActionsTemplate: Signal<RtThreadListRowActionsDirective<TRow> | undefined> = contentChild(\n RtThreadListRowActionsDirective<TRow>\n );\n\n protected readonly filtersTemplate: Signal<RtThreadListFiltersDirective | undefined> = contentChild(RtThreadListFiltersDirective);\n\n protected readonly searchTemplate: Signal<RtThreadListSearchDirective | undefined> = contentChild(RtThreadListSearchDirective);\n\n public readonly rows: InputSignal<readonly TRow[]> = input<readonly TRow[]>([]);\n\n public readonly activeId: InputSignal<IRtThreadList.TRowId | null> = input<IRtThreadList.TRowId | null>(null);\n\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly searchPlaceholder: InputSignal<string> = input<string>('');\n\n public readonly emptyText: InputSignal<string> = input<string>('');\n\n /** Значки декоративных строк-превью пустого состояния, по строке на значок */\n public readonly emptyPreviewIcons: InputSignal<readonly IRtIcon.Name[]> = input<readonly IRtIcon.Name[]>(PREVIEW_ICONS);\n\n public readonly loading: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly fetching: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly hasMore: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n public readonly filtersActive: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n\n // Имя `select` зарезервировано под нативное DOM-событие\n // (@angular-eslint/no-output-native), поэтому output переименован.\n public readonly selectRow: OutputEmitterRef<IRtThreadList.TRowId> = output<IRtThreadList.TRowId>();\n\n // Ctrl/⌘+клик по строке: потребитель открывает строку в новой вкладке.\n // Обычный клик остаётся на `selectRow`.\n public readonly openInNewTab: OutputEmitterRef<IRtThreadList.TRowId> = output<IRtThreadList.TRowId>();\n\n public readonly searchChange: OutputEmitterRef<string> = output<string>();\n\n public readonly loadMore: OutputEmitterRef<void> = output<void>();\n\n public ngOnInit(): void {\n // Дебаунс непустого ввода; очистка крестиком применяется сразу (searchDebounce).\n this.searchControl.valueChanges\n .pipe(\n map((value: string): string => value.trim()),\n searchDebounce(),\n distinctUntilChanged(),\n takeUntilDestroyed(this.#destroyRef)\n )\n .subscribe((value: string): void => this.searchChange.emit(value));\n }\n\n protected onSelect(id: IRtThreadList.TRowId, event: MouseEvent): void {\n // Ctrl (Win/Linux) или ⌘ (macOS) — «открыть в новой вкладке», как у\n // нативных ссылок. Иначе — обычный выбор строки в текущей вкладке.\n if (event.ctrlKey || event.metaKey) {\n this.openInNewTab.emit(id);\n return;\n }\n this.selectRow.emit(id);\n }\n\n protected onLoadMore(): void {\n this.loadMore.emit();\n }\n}\n","<ng-container rtBlock=\"rt-thread-list\">\n <header rtElem=\"head\">\n @if (searchTemplate()) {\n <div rtElem=\"search\" qa-dataid=\"thread-list-search\">\n <ng-container [ngTemplateOutlet]=\"searchTemplate()?.templateRef ?? null\" />\n </div>\n } @else {\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"thread-list-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchPlaceholderText()\"\n [formControl]=\"searchControl\" />\n }\n @if (filtersTemplate()) {\n <rt-icon-button\n rtElem=\"filter-trigger\"\n qa-dataid=\"thread-list-filter\"\n icon=\"filter\"\n variant=\"secondary\"\n rtPopoverAlign=\"end\"\n [ariaLabel]=\"t().uiFilters\"\n [indicator]=\"filtersActive()\"\n [rtPopover]=\"filtersPanel\" />\n }\n </header>\n\n <ng-template #rowButton let-row>\n <button\n rtElem=\"row\"\n qa-dataid=\"thread-list-row\"\n type=\"button\"\n [attr.data-id]=\"row.id\"\n [attr.data-unread]=\"row.hasUnread\"\n [attr.aria-current]=\"row.id === activeId() ? 'true' : null\"\n [rtMod]=\"{\n active: row.id === activeId(),\n unread: row.hasUnread,\n overdue: !!row.overdue,\n }\"\n (click)=\"onSelect(row.id, $event)\">\n @if (row.sign; as sign) {\n <rt-service-logo rtElem=\"row-sign\" qa-dataid=\"thread-list-row-sign\" size=\"xs\" [logos]=\"[sign]\" />\n <span rtElem=\"row-content\">\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </span>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowContent\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n </button>\n </ng-template>\n\n <ng-template #rowContent let-row>\n <ng-container [ngTemplateOutlet]=\"rowTemplate()?.templateRef ?? null\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </ng-template>\n\n <ng-template #filtersPanel>\n <div rtElem=\"filters-panel\" qa-dataid=\"thread-list-filters-panel\">\n <ng-container [ngTemplateOutlet]=\"filtersTemplate()?.templateRef ?? null\" />\n </div>\n </ng-template>\n\n <div rtElem=\"rows\" qa-dataid=\"thread-list-rows\">\n @if (loading() && !rows().length) {\n @for (i of skeletonRows; track i) {\n <div rtElem=\"row-skeleton\" qa-dataid=\"thread-list-row-skeleton\" aria-hidden=\"true\">\n <rt-skeleton width=\"60%\" height=\"14px\" />\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n } @else if (!rows().length) {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"thread-list-empty\" [description]=\"t().uiThreadListEmptyHint\" [title]=\"emptyTitle()\">\n <div rtEmptyIllustration rtElem=\"empty-preview\">\n @for (row of emptyPreviewRows(); track row.id) {\n <div rtElem=\"empty-card\" [rtMod]=\"{ offset: row.offset }\">\n <span rtElem=\"empty-avatar\">\n <rt-icon size=\"sm\" [name]=\"row.icon\" />\n </span>\n <span rtElem=\"empty-lines\">\n <span rtElem=\"empty-line\" [rtMod]=\"{ short: true }\"></span>\n <span rtElem=\"empty-line\"></span>\n </span>\n </div>\n }\n </div>\n </rt-empty-state>\n } @else {\n @for (row of rows(); track row.id) {\n @if (rowActionsTemplate(); as actions) {\n <div rtElem=\"row-wrap\" qa-dataid=\"thread-list-row-wrap\">\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n <div rtElem=\"row-actions\" qa-dataid=\"thread-list-row-actions\">\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n </div>\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"rowButton\" [ngTemplateOutletContext]=\"{ $implicit: row }\" />\n }\n }\n @if (fetching()) {\n <div rtElem=\"row-loader\" qa-dataid=\"thread-list-row-loader\">\n <rt-skeleton width=\"90%\" height=\"12px\" />\n </div>\n }\n @if (hasMore()) {\n <div\n rtElem=\"load-anchor\"\n qa-dataid=\"thread-list-load-more\"\n aria-hidden=\"true\"\n rtInfiniteScroll\n [disabled]=\"fetching()\"\n (loadMore)=\"onLoadMore()\"></div>\n }\n }\n </div>\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input, numberAttribute } from "@angular/core";
|
|
3
|
+
import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
|
|
4
|
+
import { rtKitLabel } from "@rt-tools/ui-kit-v2/core";
|
|
5
|
+
import { RtTooltipDirective } from "@rt-tools/ui-kit-v2/tooltip";
|
|
6
|
+
const BEM_BLOCK = "rt-usage-ring";
|
|
7
|
+
const RING_RADIUS = 7.75;
|
|
8
|
+
const RT_USAGE_RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS;
|
|
9
|
+
function rtUsagePercent(value) {
|
|
10
|
+
if (!Number.isFinite(value)) return 0;
|
|
11
|
+
return Math.min(100, Math.max(0, Math.round(value)));
|
|
12
|
+
}
|
|
13
|
+
var RtUsageRingComponent = class RtUsageRingComponent {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.percent = computed(() => rtUsagePercent(this.value()), ...ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []);
|
|
16
|
+
this.radius = RING_RADIUS;
|
|
17
|
+
this.circumference = RT_USAGE_RING_CIRCUMFERENCE;
|
|
18
|
+
this.dashOffset = computed(() => RT_USAGE_RING_CIRCUMFERENCE * (1 - this.percent() / 100), ...ngDevMode ? [{ debugName: "dashOffset" }] : /* istanbul ignore next */ []);
|
|
19
|
+
this.mods = computed(() => ({ warning: this.percent() >= this.warnAt() }), ...ngDevMode ? [{ debugName: "mods" }] : /* istanbul ignore next */ []);
|
|
20
|
+
this.label = rtKitLabel("aiUsageAria", computed(() => ({ percent: this.percent() })));
|
|
21
|
+
this.value = input(0, {
|
|
22
|
+
...ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {},
|
|
23
|
+
transform: numberAttribute
|
|
24
|
+
});
|
|
25
|
+
this.warnAt = input(80, {
|
|
26
|
+
...ngDevMode ? { debugName: "warnAt" } : /* istanbul ignore next */ {},
|
|
27
|
+
transform: numberAttribute
|
|
28
|
+
});
|
|
29
|
+
this.hint = input("", ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
|
|
30
|
+
}
|
|
31
|
+
static {
|
|
32
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
33
|
+
minVersion: "12.0.0",
|
|
34
|
+
version: "22.2.2",
|
|
35
|
+
ngImport: i0,
|
|
36
|
+
type: RtUsageRingComponent,
|
|
37
|
+
deps: [],
|
|
38
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
static {
|
|
42
|
+
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
43
|
+
minVersion: "17.1.0",
|
|
44
|
+
version: "22.2.2",
|
|
45
|
+
type: RtUsageRingComponent,
|
|
46
|
+
isStandalone: true,
|
|
47
|
+
selector: "rt-usage-ring",
|
|
48
|
+
inputs: {
|
|
49
|
+
value: {
|
|
50
|
+
classPropertyName: "value",
|
|
51
|
+
publicName: "value",
|
|
52
|
+
isSignal: true,
|
|
53
|
+
isRequired: false,
|
|
54
|
+
transformFunction: null
|
|
55
|
+
},
|
|
56
|
+
warnAt: {
|
|
57
|
+
classPropertyName: "warnAt",
|
|
58
|
+
publicName: "warnAt",
|
|
59
|
+
isSignal: true,
|
|
60
|
+
isRequired: false,
|
|
61
|
+
transformFunction: null
|
|
62
|
+
},
|
|
63
|
+
hint: {
|
|
64
|
+
classPropertyName: "hint",
|
|
65
|
+
publicName: "hint",
|
|
66
|
+
isSignal: true,
|
|
67
|
+
isRequired: false,
|
|
68
|
+
transformFunction: null
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
host: { classAttribute: "rt-usage-ring" },
|
|
72
|
+
ngImport: i0,
|
|
73
|
+
template: "<ng-container rtBlock=\"rt-usage-ring\">\n <span\n rtElem=\"ring\"\n role=\"img\"\n qa-dataid=\"usage-ring\"\n [rtMod]=\"mods()\"\n [attr.aria-label]=\"label()\"\n [attr.data-percent]=\"percent()\"\n [attr.tabindex]=\"hint() ? 0 : null\"\n [rtTooltip]=\"hint()\">\n <svg rtElem=\"svg\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <circle rtElem=\"track\" cx=\"9\" cy=\"9\" [attr.r]=\"radius\" />\n <circle\n rtElem=\"arc\"\n cx=\"9\"\n cy=\"9\"\n [attr.r]=\"radius\"\n [attr.stroke-dasharray]=\"circumference\"\n [attr.stroke-dashoffset]=\"dashOffset()\" />\n </svg>\n </span>\n</ng-container>\n",
|
|
74
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-usage-ring{--rt-usage-ring-size: var(--rt-control-height-sm);--rt-usage-ring-mark-size: var(--rt-space-4);--rt-usage-ring-stroke: 2.5;--rt-usage-ring-color: var(--rt-color-action-primary);--rt-usage-ring-track: var(--rt-color-border-default);--rt-usage-ring-radius: var(--rt-radius-md);--rt-usage-ring-focus-shadow: var(--rt-shadow-focus-ring);--rt-usage-ring-duration: var(--rt-duration-fast);--rt-usage-ring-arc-duration: var(--rt-duration-base);display:inline-flex;flex:none}.rt-usage-ring__ring{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--rt-usage-ring-radius);block-size:var(--rt-usage-ring-size);inline-size:var(--rt-usage-ring-size);outline:0;transition:background var(--rt-usage-ring-duration) ease}.rt-usage-ring__ring:hover,.rt-usage-ring__ring:focus-visible{background:var(--rt-color-bg-subtle)}.rt-usage-ring__ring:focus-visible{box-shadow:var(--rt-usage-ring-focus-shadow)}.rt-usage-ring__ring--warning{--rt-usage-ring-color: var(--rt-color-state-warning)}.rt-usage-ring__svg{block-size:var(--rt-usage-ring-mark-size);inline-size:var(--rt-usage-ring-mark-size);transform:rotate(-90deg)}.rt-usage-ring__track,.rt-usage-ring__arc{fill:none;stroke-width:var(--rt-usage-ring-stroke)}.rt-usage-ring__track{stroke:var(--rt-usage-ring-track)}.rt-usage-ring__arc{stroke:var(--rt-usage-ring-color);stroke-linecap:round;transition:stroke-dashoffset var(--rt-usage-ring-arc-duration) ease}}\n"],
|
|
75
|
+
dependencies: [
|
|
76
|
+
{
|
|
77
|
+
kind: "directive",
|
|
78
|
+
type: BlockDirective,
|
|
79
|
+
selector: "[rtBlock]",
|
|
80
|
+
inputs: ["rtMod"]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
kind: "directive",
|
|
84
|
+
type: ElemDirective,
|
|
85
|
+
selector: "[rtElem]",
|
|
86
|
+
inputs: ["rtMod"]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
kind: "directive",
|
|
90
|
+
type: ModDirective,
|
|
91
|
+
selector: "[rtMod]"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
kind: "directive",
|
|
95
|
+
type: RtTooltipDirective,
|
|
96
|
+
selector: "[rtTooltip]",
|
|
97
|
+
inputs: [
|
|
98
|
+
"rtTooltip",
|
|
99
|
+
"rtTooltipPlacement",
|
|
100
|
+
"rtTooltipShowDelay",
|
|
101
|
+
"rtTooltipWhenTruncated",
|
|
102
|
+
"rtTooltipHideOnClick"
|
|
103
|
+
],
|
|
104
|
+
exportAs: ["rtTooltip"]
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
108
|
+
encapsulation: i0.ViewEncapsulation.None
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
113
|
+
minVersion: "12.0.0",
|
|
114
|
+
version: "22.2.2",
|
|
115
|
+
ngImport: i0,
|
|
116
|
+
type: RtUsageRingComponent,
|
|
117
|
+
decorators: [{
|
|
118
|
+
type: Component,
|
|
119
|
+
args: [{
|
|
120
|
+
selector: "rt-usage-ring",
|
|
121
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
122
|
+
encapsulation: ViewEncapsulation.None,
|
|
123
|
+
imports: [
|
|
124
|
+
BlockDirective,
|
|
125
|
+
ElemDirective,
|
|
126
|
+
ModDirective,
|
|
127
|
+
RtTooltipDirective
|
|
128
|
+
],
|
|
129
|
+
host: { class: BEM_BLOCK },
|
|
130
|
+
template: "<ng-container rtBlock=\"rt-usage-ring\">\n <span\n rtElem=\"ring\"\n role=\"img\"\n qa-dataid=\"usage-ring\"\n [rtMod]=\"mods()\"\n [attr.aria-label]=\"label()\"\n [attr.data-percent]=\"percent()\"\n [attr.tabindex]=\"hint() ? 0 : null\"\n [rtTooltip]=\"hint()\">\n <svg rtElem=\"svg\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <circle rtElem=\"track\" cx=\"9\" cy=\"9\" [attr.r]=\"radius\" />\n <circle\n rtElem=\"arc\"\n cx=\"9\"\n cy=\"9\"\n [attr.r]=\"radius\"\n [attr.stroke-dasharray]=\"circumference\"\n [attr.stroke-dashoffset]=\"dashOffset()\" />\n </svg>\n </span>\n</ng-container>\n",
|
|
131
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-usage-ring{--rt-usage-ring-size: var(--rt-control-height-sm);--rt-usage-ring-mark-size: var(--rt-space-4);--rt-usage-ring-stroke: 2.5;--rt-usage-ring-color: var(--rt-color-action-primary);--rt-usage-ring-track: var(--rt-color-border-default);--rt-usage-ring-radius: var(--rt-radius-md);--rt-usage-ring-focus-shadow: var(--rt-shadow-focus-ring);--rt-usage-ring-duration: var(--rt-duration-fast);--rt-usage-ring-arc-duration: var(--rt-duration-base);display:inline-flex;flex:none}.rt-usage-ring__ring{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--rt-usage-ring-radius);block-size:var(--rt-usage-ring-size);inline-size:var(--rt-usage-ring-size);outline:0;transition:background var(--rt-usage-ring-duration) ease}.rt-usage-ring__ring:hover,.rt-usage-ring__ring:focus-visible{background:var(--rt-color-bg-subtle)}.rt-usage-ring__ring:focus-visible{box-shadow:var(--rt-usage-ring-focus-shadow)}.rt-usage-ring__ring--warning{--rt-usage-ring-color: var(--rt-color-state-warning)}.rt-usage-ring__svg{block-size:var(--rt-usage-ring-mark-size);inline-size:var(--rt-usage-ring-mark-size);transform:rotate(-90deg)}.rt-usage-ring__track,.rt-usage-ring__arc{fill:none;stroke-width:var(--rt-usage-ring-stroke)}.rt-usage-ring__track{stroke:var(--rt-usage-ring-track)}.rt-usage-ring__arc{stroke:var(--rt-usage-ring-color);stroke-linecap:round;transition:stroke-dashoffset var(--rt-usage-ring-arc-duration) ease}}\n"]
|
|
132
|
+
}]
|
|
133
|
+
}],
|
|
134
|
+
propDecorators: {
|
|
135
|
+
value: [{
|
|
136
|
+
type: i0.Input,
|
|
137
|
+
args: [{
|
|
138
|
+
isSignal: true,
|
|
139
|
+
alias: "value",
|
|
140
|
+
required: false
|
|
141
|
+
}]
|
|
142
|
+
}],
|
|
143
|
+
warnAt: [{
|
|
144
|
+
type: i0.Input,
|
|
145
|
+
args: [{
|
|
146
|
+
isSignal: true,
|
|
147
|
+
alias: "warnAt",
|
|
148
|
+
required: false
|
|
149
|
+
}]
|
|
150
|
+
}],
|
|
151
|
+
hint: [{
|
|
152
|
+
type: i0.Input,
|
|
153
|
+
args: [{
|
|
154
|
+
isSignal: true,
|
|
155
|
+
alias: "hint",
|
|
156
|
+
required: false
|
|
157
|
+
}]
|
|
158
|
+
}]
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
export { RT_USAGE_RING_CIRCUMFERENCE, RtUsageRingComponent, rtUsagePercent };
|
|
162
|
+
|
|
163
|
+
//# sourceMappingURL=rt-tools-ui-kit-v2-usage-ring.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-usage-ring.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/usage-ring/rt-usage-ring.component.ts","../../../projects/ui-kit-v2/src/lib/components/usage-ring/rt-usage-ring.component.html"],"sourcesContent":["import { NumberInput } from '@angular/cdk/coercion';\nimport {\n computed,\n input,\n numberAttribute,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\n\nconst BEM_BLOCK: string = 'rt-usage-ring';\n\n/** Радиус дуги в единицах рисунка: круг 18 × 18, дуга толщиной 2.5 по середине кольца. */\nconst RING_RADIUS: number = 7.75;\n\n/** Длина окружности дуги: из неё складывается доля, закрашенная по `stroke-dasharray`. */\nexport const RT_USAGE_RING_CIRCUMFERENCE: number = 2 * Math.PI * RING_RADIUS;\n\n/** Доля от 0 до 100 в целых процентах; всё вне границ прижимается к краю. */\nexport function rtUsagePercent(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n\n return Math.min(100, Math.max(0, Math.round(value)));\n}\n\n/**\n * Кольцо расхода: доля потраченного лимита дугой по кругу, с порога предупреждения оранжевая.\n *\n * Кольцо рисует только долю. Что за лимит и когда он сбрасывается, говорит подсказка `hint`\n * по наведению и фокусу: её текст собирает приложение, кит не знает ни лимита, ни дат.\n */\n@Component({\n selector: 'rt-usage-ring',\n templateUrl: './rt-usage-ring.component.html',\n styleUrl: './rt-usage-ring.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n RtTooltipDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtUsageRingComponent {\n /** Доля в целых процентах, прижатая к 0…100. */\n protected readonly percent: Signal<number> = computed((): number => rtUsagePercent(this.value()));\n\n protected readonly radius: number = RING_RADIUS;\n\n protected readonly circumference: number = RT_USAGE_RING_CIRCUMFERENCE;\n\n /** Незакрашенная часть окружности: дуга рисуется штрихом этой длины со смещением. */\n protected readonly dashOffset: Signal<number> = computed((): number => RT_USAGE_RING_CIRCUMFERENCE * (1 - this.percent() / 100));\n\n protected readonly mods: Signal<Record<string, boolean>> = computed((): Record<string, boolean> => ({\n warning: this.percent() >= this.warnAt(),\n }));\n\n protected readonly label: Signal<string> = rtKitLabel(\n 'aiUsageAria',\n computed((): Readonly<Record<string, number>> => ({ percent: this.percent() }))\n );\n\n /** Потраченная доля лимита в процентах. */\n public readonly value: InputSignalWithTransform<number, NumberInput> = input<number, NumberInput>(0, { transform: numberAttribute });\n\n /** С этой доли кольцо оранжевое. */\n public readonly warnAt: InputSignalWithTransform<number, NumberInput> = input<number, NumberInput>(80, { transform: numberAttribute });\n\n /** Подсказка по наведению и фокусу: доля и дата сброса словами приложения. Пусто — подсказки нет. */\n public readonly hint: InputSignal<string> = input<string>('');\n}\n","<ng-container rtBlock=\"rt-usage-ring\">\n <span\n rtElem=\"ring\"\n role=\"img\"\n qa-dataid=\"usage-ring\"\n [rtMod]=\"mods()\"\n [attr.aria-label]=\"label()\"\n [attr.data-percent]=\"percent()\"\n [attr.tabindex]=\"hint() ? 0 : null\"\n [rtTooltip]=\"hint()\">\n <svg rtElem=\"svg\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <circle rtElem=\"track\" cx=\"9\" cy=\"9\" [attr.r]=\"radius\" />\n <circle\n rtElem=\"arc\"\n cx=\"9\"\n cy=\"9\"\n [attr.r]=\"radius\"\n [attr.stroke-dasharray]=\"circumference\"\n [attr.stroke-dashoffset]=\"dashOffset()\" />\n </svg>\n </span>\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "@rt-tools/ui-kit-v2/core";
|
|
2
2
|
export * from "@rt-tools/ui-kit-v2/accordion";
|
|
3
|
+
export * from "@rt-tools/ui-kit-v2/ai-prompt-input";
|
|
3
4
|
export * from "@rt-tools/ui-kit-v2/ai-run-status";
|
|
4
5
|
export * from "@rt-tools/ui-kit-v2/action-bar";
|
|
5
6
|
export * from "@rt-tools/ui-kit-v2/aside-section";
|
|
@@ -101,6 +102,7 @@ export * from "@rt-tools/ui-kit-v2/toolbar";
|
|
|
101
102
|
export * from "@rt-tools/ui-kit-v2/tooltip";
|
|
102
103
|
export * from "@rt-tools/ui-kit-v2/tree";
|
|
103
104
|
export * from "@rt-tools/ui-kit-v2/tree-selector";
|
|
105
|
+
export * from "@rt-tools/ui-kit-v2/usage-ring";
|
|
104
106
|
export * from "@rt-tools/ui-kit-v2/welcome-dialog";
|
|
105
107
|
export * from "@rt-tools/ui-kit-v2/workspace-details";
|
|
106
108
|
export * from "@rt-tools/ui-kit-v2/workspace";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rt-tools/ui-kit-v2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Yauheni Krumin",
|
|
6
6
|
"type": "module",
|
|
@@ -61,6 +61,10 @@
|
|
|
61
61
|
"types": "./types/rt-tools-ui-kit-v2-action-bar.d.ts",
|
|
62
62
|
"default": "./fesm2022/rt-tools-ui-kit-v2-action-bar.mjs"
|
|
63
63
|
},
|
|
64
|
+
"./ai-prompt-input": {
|
|
65
|
+
"types": "./types/rt-tools-ui-kit-v2-ai-prompt-input.d.ts",
|
|
66
|
+
"default": "./fesm2022/rt-tools-ui-kit-v2-ai-prompt-input.mjs"
|
|
67
|
+
},
|
|
64
68
|
"./ai-run-status": {
|
|
65
69
|
"types": "./types/rt-tools-ui-kit-v2-ai-run-status.d.ts",
|
|
66
70
|
"default": "./fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs"
|
|
@@ -477,6 +481,10 @@
|
|
|
477
481
|
"types": "./types/rt-tools-ui-kit-v2-tree-selector.d.ts",
|
|
478
482
|
"default": "./fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs"
|
|
479
483
|
},
|
|
484
|
+
"./usage-ring": {
|
|
485
|
+
"types": "./types/rt-tools-ui-kit-v2-usage-ring.d.ts",
|
|
486
|
+
"default": "./fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs"
|
|
487
|
+
},
|
|
480
488
|
"./welcome-dialog": {
|
|
481
489
|
"types": "./types/rt-tools-ui-kit-v2-welcome-dialog.d.ts",
|
|
482
490
|
"default": "./fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs"
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# `rt-ai-prompt-input`
|
|
2
|
+
|
|
3
|
+
```html
|
|
4
|
+
<rt-ai-prompt-input
|
|
5
|
+
stoppable
|
|
6
|
+
model="Opus 5.5"
|
|
7
|
+
[usage]="usedPercent()"
|
|
8
|
+
[usageHint]="usageHint()"
|
|
9
|
+
[sending]="sending()"
|
|
10
|
+
[(text)]="draft"
|
|
11
|
+
(submitted)="ask($event)"
|
|
12
|
+
(stopped)="stop()"
|
|
13
|
+
(controlPicked)="openPicker($event)" />
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| вход | тип | умолчание |
|
|
17
|
+
| --------------------------- | -------------------- | ------------------------ |
|
|
18
|
+
| `placeholder` | `string` | `''` → `chatPlaceholder` |
|
|
19
|
+
| `hint` | `string \| null` | `null` → `aiDisclaimer` |
|
|
20
|
+
| `hintPosition` | `'below' \| 'above'` | `'below'` |
|
|
21
|
+
| `attachments` | `boolean` | `false` |
|
|
22
|
+
| `accept` | `string` | `''` |
|
|
23
|
+
| `model` / `effort` / `mode` | `string` | `''`, кнопки нет |
|
|
24
|
+
| `usage` | `number \| null` | `null`, кольца нет |
|
|
25
|
+
| `usageHint` | `string` | `''` |
|
|
26
|
+
| `usageWarnAt` | `number` | `80` |
|
|
27
|
+
| `sending` / `stoppable` | `boolean` | `false` |
|
|
28
|
+
| `disabled` | `boolean` | `false` |
|
|
29
|
+
| `minRows` / `maxRows` | `number` | 1 / 8 |
|
|
30
|
+
| `text` (model) | `string` | `''` |
|
|
31
|
+
|
|
32
|
+
Выходы: `submitted` отдаёт `{ text, files }`, `stopped` сообщает о нажатой «Стоп». Выход
|
|
33
|
+
`controlPicked` отдаёт `'model'`, `'effort'` или `'mode'`. Метод: `focus()`.
|
|
34
|
+
|
|
35
|
+
Спек лежит в `docs/specs/ui-kit-v2/ai-chat/`; здесь только устройство папки.
|
|
36
|
+
|
|
37
|
+
## Главное, что нужно знать
|
|
38
|
+
|
|
39
|
+
**Одна рамка: текст сверху, ряд действий внутри снизу.** Слева «+», справа модель, усилие,
|
|
40
|
+
режим, кольцо расхода и отправка. Элемент ряда без значения не рисуется.
|
|
41
|
+
|
|
42
|
+
**Что открывает модель, усилие и режим, решает приложение.** Поле сообщает, какую кнопку нажали,
|
|
43
|
+
и показывает подпись, которую ему дали.
|
|
44
|
+
|
|
45
|
+
**Подсказка стоит отдельной строкой под полем или над ним.** В ряд действий она не входит.
|
|
46
|
+
Пустая строка `hint` её убирает.
|
|
47
|
+
|
|
48
|
+
**`stoppable` меняет смысл `sending`.** При обоих флагах стрелку сменяет «Стоп», поле открыто, и
|
|
49
|
+
следующий вопрос набирается, пока идёт ответ. Без `stoppable` отправка закрывает поле.
|
|
50
|
+
|
|
51
|
+
## Края
|
|
52
|
+
|
|
53
|
+
- Отправка идёт по `Enter` без Shift или по стрелке. `Shift+Enter` переносит строку, подтверждение
|
|
54
|
+
набора IME не перехватывается.
|
|
55
|
+
- Пробелы текстом не считаются, один приложенный файл открывает отправку и без текста.
|
|
56
|
+
|
|
57
|
+
## Рядом
|
|
58
|
+
|
|
59
|
+
- [`rt-usage-ring`](../usage-ring/CONTEXT.md): кольцо расхода в ряду действий.
|
|
60
|
+
- `rt-message-composer` входа `rich-editor`: поле переписки с людьми, капсула и форматирование.
|