@rt-tools/ui-kit-v2 0.34.5 → 0.35.1

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.
Files changed (76) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-ai-prompt-input.mjs +574 -0
  2. package/fesm2022/rt-tools-ui-kit-v2-ai-prompt-input.mjs.map +1 -0
  3. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +2 -1
  4. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +2 -1
  6. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +62 -3
  8. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +4 -2
  10. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +2 -1
  12. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +4 -2
  14. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +2 -1
  16. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +2 -1
  18. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +2 -1
  20. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +2 -1
  22. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +2 -1
  24. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +2 -1
  26. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
  27. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs +2 -2
  28. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs.map +1 -1
  29. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +4 -2
  30. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  31. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +148 -24
  32. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  33. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +2 -1
  34. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
  35. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +4 -2
  36. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
  37. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +2 -1
  38. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
  39. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +2 -1
  40. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  41. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +2 -1
  42. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  43. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +2 -1
  44. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  45. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +52 -5
  46. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
  47. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +2 -1
  48. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
  49. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +37 -0
  50. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
  51. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +2 -1
  52. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
  53. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +2 -1
  54. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
  55. package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs +164 -0
  56. package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs.map +1 -0
  57. package/fesm2022/rt-tools-ui-kit-v2.mjs +2 -0
  58. package/package.json +9 -1
  59. package/src/lib/components/ai-prompt-input/CONTEXT.md +60 -0
  60. package/src/lib/components/ai-prompt-input/rt-ai-prompt-input.component.scss +113 -0
  61. package/src/lib/components/markdown-text/rt-markdown-text.component.scss +3 -0
  62. package/src/lib/components/thread-list/rt-thread-list.component.scss +26 -11
  63. package/src/lib/components/tooltip/CONTEXT.md +4 -0
  64. package/src/lib/components/usage-ring/CONTEXT.md +33 -0
  65. package/src/lib/components/usage-ring/rt-usage-ring.component.scss +64 -0
  66. package/src/rich-editor/lib/components/ai-chat/CONTEXT.md +1 -1
  67. package/src/rich-editor/lib/components/ai-chat/answer/rt-ai-chat-answer.component.scss +1 -0
  68. package/src/rich-editor/lib/components/ai-chat/rt-ai-chat.component.scss +6 -0
  69. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +25 -0
  70. package/types/rt-tools-ui-kit-v2-ai-prompt-input.d.ts +193 -0
  71. package/types/rt-tools-ui-kit-v2-core.d.ts +4 -0
  72. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +56 -3
  73. package/types/rt-tools-ui-kit-v2-thread-list.d.ts +7 -1
  74. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +12 -0
  75. package/types/rt-tools-ui-kit-v2-usage-ring.d.ts +47 -0
  76. package/types/rt-tools-ui-kit-v2.d.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-tree.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.directives.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.logic.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.component.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.component.html"],"sourcesContent":["import { inject, Directive, TemplateRef } from '@angular/core';\n\nimport { IRtTree } from './rt-tree.model';\n\n/**\n * Разметка приложения в конце каждой строки `rt-tree`. Узел строки приходит в контексте как\n * `$implicit`: дерево не заводит вход под каждый такой элемент.\n */\n@Directive({ selector: 'ng-template[rtTreeNodeEnd]' })\nexport class RtTreeNodeEndDirective<TValue> {\n public readonly templateRef: TemplateRef<IRtTree.NodeContext<TValue>> = inject<TemplateRef<IRtTree.NodeContext<TValue>>>(TemplateRef);\n}\n\n/**\n * Разметка приложения под подписью строки, в одной линии с метками узла. Узел строки приходит в\n * контексте как `$implicit`.\n */\n@Directive({ selector: 'ng-template[rtTreeNodeMeta]' })\nexport class RtTreeNodeMetaDirective<TValue> {\n public readonly templateRef: TemplateRef<IRtTree.NodeContext<TValue>> = inject<TemplateRef<IRtTree.NodeContext<TValue>>>(TemplateRef);\n}\n","import { IRtMatchPart, rtMatchParts, rtTreeBranchState, rtTreeLeaves } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTree } from './rt-tree.model';\n\n/**\n * Расчёт выбора `rt-tree` — чистые функции над неизменяемыми узлами.\n *\n * Строки, листья и отметки ветвей считает модуль дерева выбора из списка: здесь только то, чего у\n * выбора из списка нет — режим отметок, выключенный каскад и «выбрать всё». Узлы не меняются\n * никогда: каждая функция отвечает новым массивом выбора.\n */\n\ntype TNode<TValue> = IRtTree.Node<TValue>;\n\nfunction isBranch<TValue>(node: TNode<TValue>): boolean {\n return (node.children ?? []).length > 0;\n}\n\nfunction without<TValue>(value: ReadonlyArray<TValue>, drop: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return value.filter((item: TValue): boolean => !drop.includes(item));\n}\n\nfunction withAll<TValue>(value: ReadonlyArray<TValue>, add: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return [...value, ...add.filter((item: TValue): boolean => !value.includes(item))];\n}\n\n/**\n * Отметка строки. В каскаде ветка отмечена по своим листьям; без каскада и у листа — по тому,\n * лежит ли в выборе сам узел.\n */\nexport function rtTreeMark<TValue>(node: TNode<TValue>, value: ReadonlyArray<TValue>, cascade: boolean): IRtTree.Mark {\n if (cascade && isBranch(node)) {\n return rtTreeBranchState(node, value);\n }\n return value.includes(node.value) ? 'all' : 'none';\n}\n\n/**\n * Выбор после клика по узлу. Выключенный узел выбор не меняет. Одиночный режим держит один узел и\n * не снимает его повторным кликом. В каскаде ветка добавляет свои включённые листья или снимает\n * их, когда выбраны все; выключенные листья остаются как были.\n */\nexport function rtTreeChoose<TValue>(\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>,\n mode: IRtTree.Mode,\n cascade: boolean\n): ReadonlyArray<TValue> {\n if (node.disabled || mode === 'none') {\n return value;\n }\n if (mode === 'single') {\n return [node.value];\n }\n if (cascade && isBranch(node)) {\n const leaves: ReadonlyArray<TValue> = rtTreeLeaves(node);\n return rtTreeBranchState(node, value) === 'all' ? without(value, leaves) : withAll(value, leaves);\n }\n return value.includes(node.value) ? without(value, [node.value]) : withAll(value, [node.value]);\n}\n\n/**\n * Включённые листья видимых строк. Раскрытая ветка отдаёт листья своими строками ниже, свёрнутая —\n * всеми листьями под собой: они видимы через неё.\n */\nexport function rtTreeVisibleLeaves<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>): ReadonlyArray<TValue> {\n return rows.flatMap((row: IRtTree.Row<TValue>): ReadonlyArray<TValue> => (row.branch && row.open ? [] : rtTreeLeaves(row.option)));\n}\n\n/** Отметка «выбрать всё» по включённым листьям видимых строк. */\nexport function rtTreeSelectAllMark<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): IRtTree.Mark {\n const leaves: ReadonlyArray<TValue> = rtTreeVisibleLeaves(rows);\n const count: number = leaves.filter((leaf: TValue): boolean => value.includes(leaf)).length;\n if (count === 0) {\n return 'none';\n }\n return count === leaves.length ? 'all' : 'some';\n}\n\n/**\n * Выбор после клика по «выбрать всё»: включённые листья видимых строк добавляются, а когда выбраны\n * все — снимаются. Выключенные листья `rtTreeLeaves` не отдаёт, поэтому их состояние не меняется.\n */\nexport function rtTreeSelectAll<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n const leaves: ReadonlyArray<TValue> = rtTreeVisibleLeaves(rows);\n return rtTreeSelectAllMark(rows, value) === 'all' ? without(value, leaves) : withAll(value, leaves);\n}\n\n/**\n * Подпись, описание и метки узла, разрезанные по каждому слову запроса тем же резом, что у поиска\n * меню: приложение делит поиск по пробелам, и найденное слово видно там, где оно нашлось.\n */\nexport function rtTreeLabelParts<TValue>(node: TNode<TValue>, term: string): IRtTree.LabelParts {\n return {\n label: rtMatchParts(node.label, term),\n description: rtMatchParts(node.description ?? '', term),\n badges: (node.badges ?? []).map((badge: IRtTree.Badge): ReadonlyArray<IRtMatchPart> => rtMatchParts(badge.text, term)),\n };\n}\n\n/** Значения узла и всех его потомков. */\nfunction covered<TValue>(node: TNode<TValue>): ReadonlyArray<TValue> {\n return [node.value, ...(node.children ?? []).flatMap((child: TNode<TValue>): ReadonlyArray<TValue> => covered(child))];\n}\n\n/** Значения выключенных узлов дерева: их состояние не меняет ни одно действие. */\nfunction disabledValues<TValue>(nodes: ReadonlyArray<TNode<TValue>>): ReadonlyArray<TValue> {\n return nodes.flatMap((node: TNode<TValue>): ReadonlyArray<TValue> => [\n ...(node.disabled ? [node.value] : []),\n ...disabledValues(node.children ?? []),\n ]);\n}\n\n/** Что остаётся от выбора перед кликом без Ctrl и Cmd: то, что покрывает сам узел, и выключенные узлы. */\nexport function rtTreeAloneBase<TValue>(\n nodes: ReadonlyArray<TNode<TValue>>,\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>\n): ReadonlyArray<TValue> {\n const keep: ReadonlyArray<TValue> = [...covered(node), ...disabledValues(nodes)];\n return value.filter((item: TValue): boolean => keep.includes(item));\n}\n\n/**\n * Выбор после клика без Ctrl и Cmd в режиме, где клик выбирает один узел. Из выбора остаётся только\n * то, что покрывает сам узел, и выключенные узлы; дальше клик работает как обычно — поэтому\n * повторный клик по единственному выбранному снимает его.\n */\nexport function rtTreeChooseAlone<TValue>(\n nodes: ReadonlyArray<TNode<TValue>>,\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>,\n cascade: boolean\n): ReadonlyArray<TValue> {\n if (node.disabled) {\n return value;\n }\n return rtTreeChoose(node, rtTreeAloneBase(nodes, node, value), 'multiple', cascade);\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n contentChild,\n inject,\n input,\n model,\n output,\n signal,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n ModelSignal,\n OutputEmitterRef,\n Signal,\n TemplateRef,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon, RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtCheckboxComponent } from '@rt-tools/ui-kit-v2/checkbox';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtRadioButtonComponent } from '@rt-tools/ui-kit-v2/radio-button';\nimport { RtTagComponent } from '@rt-tools/ui-kit-v2/tag';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { IRtOptionTree, rtTreeOpenFor, rtTreeRows, rtTreeSideKey, rtTreeToggle } from '@rt-tools/ui-kit-v2/core';\nimport { RtTreeNodeEndDirective, RtTreeNodeMetaDirective } from './rt-tree.directives';\nimport { rtTreeChoose, rtTreeChooseAlone, rtTreeLabelParts, rtTreeMark, rtTreeSelectAll, rtTreeSelectAllMark } from './rt-tree.logic';\nimport { IRtTree } from './rt-tree.model';\n\nconst BEM_BLOCK: string = 'rt-tree';\n\n/** Видимая строка с тем, что разметке нужно о ней знать. */\ninterface IRtTreeView<TValue> {\n readonly row: IRtTree.Row<TValue>;\n readonly mark: IRtTree.Mark;\n /** Рисуется ли у строки флажок или радио: у групп без отметок его нет. */\n readonly marked: boolean;\n /** Радио вместо флажка. */\n readonly radio: boolean;\n /** Строка выключена: свой `disabled` у узла или выключено всё дерево. */\n readonly disabled: boolean;\n /** Число выбранного под группой в конце строки; `null` — числа нет. */\n readonly count: number | null;\n readonly parts: IRtTree.LabelParts;\n readonly highlighted: boolean;\n}\n\n/**\n * Дерево выбора, стоящее на странице само по себе.\n *\n * Строки, листья, отметки ветвей, отбор по слову и боковые стрелки считает модуль дерева выбора\n * из списка — тот же, что у `rt-select` и `rt-multiselect`. Выбор живёт в `value`; узлы не\n * меняются. Раскрытые ветки и подсвеченная строка — состояние самого дерева.\n *\n * Клавиатура идёт через `handleKeydown`: его зовёт и само дерево с фокуса на себе, и приложение\n * со своего поля поиска. Ответ — взята ли клавиша: чужую дерево не трогает.\n */\n@Component({\n selector: 'rt-tree',\n templateUrl: './rt-tree.component.html',\n styleUrl: './rt-tree.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n NgTemplateOutlet,\n FormsModule,\n RtCheckboxComponent,\n RtIconComponent,\n RtRadioButtonComponent,\n RtTagComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n role: 'tree',\n '[attr.tabindex]': 'disabled() ? -1 : 0',\n '[attr.aria-disabled]': 'disabled() || null',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-multiselectable]': \"mode() === 'multiple'\",\n '(keydown)': 'handleKeydown($event)',\n },\n})\nexport class RtTreeComponent<TValue> {\n readonly #open: WritableSignal<ReadonlySet<TValue> | null> = signal<ReadonlySet<TValue> | null>(null);\n readonly #highlighted: WritableSignal<TValue | null> = signal<TValue | null>(null);\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly nodeEnd: Signal<RtTreeNodeEndDirective<TValue> | undefined> = contentChild(RtTreeNodeEndDirective);\n\n protected readonly nodeMeta: Signal<RtTreeNodeMetaDirective<TValue> | undefined> = contentChild(RtTreeNodeMetaDirective);\n\n /** Разметка в конце строки: вход раньше директивы — обёртка вроде селектора отдаёт её входом. */\n protected readonly endTemplate: Signal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = computed(\n (): TemplateRef<IRtTree.NodeContext<TValue>> | null => this.nodeEndTemplate() ?? this.nodeEnd()?.templateRef ?? null\n );\n\n /** Разметка под подписью: вход раньше директивы. */\n protected readonly metaTemplate: Signal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = computed(\n (): TemplateRef<IRtTree.NodeContext<TValue>> | null => this.nodeMetaTemplate() ?? this.nodeMeta()?.templateRef ?? null\n );\n\n /** Раскрытые ветки: до первого действия человека — ветки над выбранным. */\n protected readonly openBranches: Signal<ReadonlySet<TValue>> = computed(\n (): ReadonlySet<TValue> => this.#open() ?? rtTreeOpenFor(this.nodes(), this.value())\n );\n\n protected readonly rows: Signal<ReadonlyArray<IRtTree.Row<TValue>>> = computed((): ReadonlyArray<IRtTree.Row<TValue>> =>\n rtTreeRows(this.nodes(), this.openBranches(), this.filter() ? this.searchTerm() : '')\n );\n\n protected readonly views: Signal<ReadonlyArray<IRtTreeView<TValue>>> = computed((): ReadonlyArray<IRtTreeView<TValue>> => {\n const value: ReadonlyArray<TValue> = this.value();\n const cascade: boolean = this.cascade();\n const term: string = this.searchTerm();\n const highlighted: TValue | null = this.#highlighted();\n const mode: IRtTree.Mode = this.mode();\n const branchMarks: boolean = this.branchMarks();\n const treeDisabled: boolean = this.disabled();\n return this.rows().map((row: IRtTree.Row<TValue>): IRtTreeView<TValue> => {\n const marked: boolean = mode !== 'none' && (branchMarks || !row.branch);\n const state: IRtTree.RowState = this.rowState(row, value, cascade);\n return {\n row,\n marked,\n mark: state.mark,\n radio: state.radio,\n disabled: treeDisabled || !!row.option.disabled,\n count: marked ? null : state.count,\n parts: rtTreeLabelParts(row.option, term),\n highlighted: row.option.value === highlighted,\n };\n });\n });\n\n protected readonly selectAllMark: Signal<IRtTree.Mark> = computed((): IRtTree.Mark => this.selectAllMarkOf(this.rows(), this.value()));\n\n protected readonly isSelectAllShown: Signal<boolean> = computed(\n (): boolean => this.showSelectAll() && this.cascade() && this.mode() === 'multiple' && this.rows().length > 0\n );\n\n /** Отметка «выбрать всё» встаёт над отметкой первой строки; у строки без отметки — над стрелкой. */\n protected readonly isSelectAllUnderMark: Signal<boolean> = computed((): boolean => this.views()[0]?.marked ?? false);\n\n /** Первая строка — лист: там, где у листа нет места под стрелку, его нет и у «выбрать всё». */\n protected readonly isSelectAllOverLeaf: Signal<boolean> = computed((): boolean => this.views()[0]?.row.branch === false);\n\n protected readonly emptyText: Signal<string> = computed((): string =>\n this.nodes().length > 0 ? this.t().uiNothingFound : this.t().uiNoOptions\n );\n\n public readonly nodes: InputSignal<ReadonlyArray<IRtTree.Node<TValue>>> = input.required<ReadonlyArray<IRtTree.Node<TValue>>>();\n public readonly value: ModelSignal<ReadonlyArray<TValue>> = model<ReadonlyArray<TValue>>([]);\n public readonly mode: InputSignal<IRtTree.Mode> = input<IRtTree.Mode>('multiple');\n public readonly cascade: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, { transform: booleanAttribute });\n public readonly searchTerm: InputSignal<string> = input<string>('');\n public readonly showSelectAll: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n public readonly ariaLabel: InputSignal<string | null> = input<string | null>(null);\n\n /** Отметки у групп. Без них клик, пробел и Enter по группе раскрывают и сворачивают её. */\n public readonly branchMarks: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, {\n transform: booleanAttribute,\n });\n\n /** Клик без Ctrl и Cmd выбирает узел один; с Ctrl или Cmd добавляет к выбору. Только для флажков. */\n public readonly exclusive: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n /** Скрывает ли слово поиска строки. Без отбора строки отбирает приложение, а слово только отмечено. */\n public readonly filter: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, {\n transform: booleanAttribute,\n });\n\n /** Выключенное дерево не меняет выбор ни кликом, ни клавишей, ни «выбрать всё»; ветки раскрываются стрелкой. */\n /** Значок кита над подписью пустого дерева. Без него пустое дерево — одна подпись. */\n public readonly emptyIcon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /**\n * Разметка в конце каждой строки, отданная входом. Нужна компоненту, который оборачивает дерево и\n * не может положить в него директиву `rtTreeNodeEnd`; вход сильнее директивы.\n */\n public readonly nodeEndTemplate: InputSignal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = input<TemplateRef<\n IRtTree.NodeContext<TValue>\n > | null>(null);\n\n /** Разметка под подписью каждой строки, отданная входом; вход сильнее директивы `rtTreeNodeMeta`. */\n public readonly nodeMetaTemplate: InputSignal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = input<TemplateRef<\n IRtTree.NodeContext<TValue>\n > | null>(null);\n\n public readonly disabled: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n public readonly picked: OutputEmitterRef<IRtTree.Node<TValue>> = output<IRtTree.Node<TValue>>();\n\n /**\n * Клавиша для дерева. Отвечает, взята ли она: не взятая идёт дальше нетронутой, поэтому\n * приложение может отдавать сюда каждую клавишу своего поля поиска.\n */\n public handleKeydown(event: KeyboardEvent): boolean {\n if (this.disabled()) {\n return false;\n }\n const taken: boolean = this.#takeKey(event.key, event.ctrlKey || event.metaKey);\n if (taken) {\n event.preventDefault();\n event.stopPropagation();\n }\n return taken;\n }\n\n public expandAll(): void {\n const all: Set<TValue> = new Set<TValue>();\n this.#collectBranches(this.nodes(), all);\n this.#open.set(all);\n }\n\n public collapseAll(): void {\n this.#open.set(new Set<TValue>());\n }\n\n public clearHighlight(): void {\n this.#highlighted.set(null);\n }\n\n protected onRowClick(row: IRtTree.Row<TValue>, event: MouseEvent): void {\n if (this.disabled()) {\n return;\n }\n this.#highlighted.set(row.option.value);\n if (row.option.disabled) {\n return;\n }\n if (this.#opensOnly(row)) {\n this.#toggleOrPick(row);\n return;\n }\n this.#choose(this.nextChoice(row.option, event.ctrlKey || event.metaKey));\n }\n\n protected onToggleClick(event: Event, value: TValue): void {\n event.stopPropagation();\n this.#toggle(value);\n }\n\n protected onSelectAll(): void {\n if (this.disabled()) {\n return;\n }\n this.#choose(this.selectAllChoice(this.rows(), this.value()));\n }\n\n /**\n * Отметка строки, её вид и число выбранного под ней. Дерево числа не рисует; наследник со своими\n * правилами выбора считает всё это по ним.\n */\n protected rowState(row: IRtTree.Row<TValue>, value: ReadonlyArray<TValue>, cascade: boolean): IRtTree.RowState {\n return { mark: rtTreeMark(row.option, value, cascade), radio: this.mode() === 'single', count: null };\n }\n\n protected selectAllMarkOf(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): IRtTree.Mark {\n return rtTreeSelectAllMark(rows, value);\n }\n\n protected selectAllChoice(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return rtTreeSelectAll(rows, value);\n }\n\n /** Выбор после действия над узлом: в исключающем режиме без Ctrl и Cmd узел остаётся один. */\n protected nextChoice(node: IRtTree.Node<TValue>, additive: boolean): ReadonlyArray<TValue> {\n if (this.exclusive() && this.mode() === 'multiple' && !additive) {\n return rtTreeChooseAlone(this.nodes(), node, this.value(), this.cascade());\n }\n return rtTreeChoose(node, this.value(), this.mode(), this.cascade());\n }\n\n /** Строка, клик по которой ничего не отмечает: режим без отметок или группа без флажка. */\n #opensOnly(row: IRtTree.Row<TValue>): boolean {\n return this.mode() === 'none' || (row.branch && !this.branchMarks());\n }\n\n #toggleOrPick(row: IRtTree.Row<TValue>): void {\n if (row.branch) {\n this.#toggle(row.option.value);\n } else {\n this.picked.emit(row.option);\n }\n }\n\n #collectBranches(list: ReadonlyArray<IRtTree.Node<TValue>>, into: Set<TValue>): void {\n list.forEach((node: IRtTree.Node<TValue>): void => {\n if ((node.children ?? []).length > 0) {\n into.add(node.value);\n this.#collectBranches(node.children ?? [], into);\n }\n });\n }\n\n /**\n * Меняет выбор, не трогая раскрытие. Пока ветки никто не раскрывал руками, раскрытие считается из\n * выбора, и без этой фиксации отметка ветки сворачивала или раскрывала её саму.\n */\n #choose(next: ReadonlyArray<TValue>): void {\n this.#open.set(this.openBranches());\n this.value.set(next);\n }\n\n #toggle(value: TValue): void {\n this.#open.set(rtTreeToggle(this.openBranches(), value));\n }\n\n #highlightedIndex(): number {\n const highlighted: TValue | null = this.#highlighted();\n return this.rows().findIndex((row: IRtTree.Row<TValue>): boolean => row.option.value === highlighted);\n }\n\n #takeKey(key: string, additive: boolean): boolean {\n const rows: ReadonlyArray<IRtTree.Row<TValue>> = this.rows();\n const index: number = this.#highlightedIndex();\n if (key === 'ArrowDown' || key === 'ArrowUp') {\n return this.#move(rows, index, key === 'ArrowDown' ? 1 : -1);\n }\n return index >= 0 && this.#takeRowKey(rows, index, key, additive);\n }\n\n /** Клавиши, которым нужна подсвеченная строка. */\n #takeRowKey(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, key: string, additive: boolean): boolean {\n if (key === 'Home' || key === 'End') {\n return this.#edge(rows, key);\n }\n if (key === 'ArrowRight' || key === 'ArrowLeft') {\n this.#side(rows, index, key);\n return true;\n }\n if (key === ' ') {\n this.#space(rows[index], additive);\n return true;\n }\n if (key === 'Enter') {\n this.#enter(rows[index], additive);\n return true;\n }\n return false;\n }\n\n #move(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, step: number): boolean {\n if (rows.length === 0) {\n return false;\n }\n const next: number = index < 0 ? 0 : Math.min(rows.length - 1, Math.max(0, index + step));\n this.#highlighted.set(rows[next].option.value);\n return true;\n }\n\n /** Home и End ведут подсветку к первой и последней строке; без подсветки они остаются у курсора поля. */\n #edge(rows: ReadonlyArray<IRtTree.Row<TValue>>, key: string): boolean {\n this.#highlighted.set(rows[key === 'Home' ? 0 : rows.length - 1].option.value);\n return true;\n }\n\n #side(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, key: string): void {\n const answer: IRtOptionTree.SideKeyAnswer<TValue> = rtTreeSideKey(rows, index, key);\n if (answer.toggle !== null) {\n this.#toggle(answer.toggle);\n }\n this.#highlighted.set(rows[answer.index].option.value);\n }\n\n #space(row: IRtTree.Row<TValue>, additive: boolean): void {\n if (this.#opensOnly(row) && row.branch) {\n this.#toggle(row.option.value);\n return;\n }\n if (!row.option.disabled && this.mode() !== 'none') {\n this.#choose(this.nextChoice(row.option, additive));\n }\n }\n\n #enter(row: IRtTree.Row<TValue>, additive: boolean): void {\n if (this.#opensOnly(row) && row.branch) {\n this.#toggle(row.option.value);\n return;\n }\n if (row.option.disabled) {\n return;\n }\n if (this.mode() !== 'none') {\n this.#choose(this.nextChoice(row.option, additive));\n }\n this.picked.emit(row.option);\n }\n}\n","<ng-container rtBlock=\"rt-tree\">\n <!--\n Строки выбираются мышью через (click); клавиатура — на самом дереве (handleKeydown), строки\n по отдельности фокус не берут: подсветка — третье состояние рядом с фокусом и выбором.\n -->\n <!-- eslint-disable @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n @if (isSelectAllShown()) {\n <div\n rtElem=\"select-all\"\n qa-dataid=\"tree-select-all\"\n role=\"presentation\"\n [rtMod]=\"{ disabled: disabled(), 'over-leaf': isSelectAllOverLeaf() }\"\n (click)=\"onSelectAll()\">\n @if (isSelectAllUnderMark()) {\n <span rtElem=\"toggle-space\"></span>\n }\n <rt-checkbox\n rtElem=\"check\"\n inert\n [disabled]=\"disabled()\"\n [indeterminate]=\"selectAllMark() === 'some'\"\n [ngModel]=\"selectAllMark() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\" />\n <span rtElem=\"label\">{{ t().uiSelectAll }}</span>\n </div>\n }\n\n @for (view of views(); track view.row.option.value) {\n <div\n rtElem=\"row\"\n qa-dataid=\"tree-row\"\n role=\"treeitem\"\n [attr.data-value]=\"view.row.option.value\"\n [attr.aria-level]=\"view.row.level + 1\"\n [attr.aria-expanded]=\"view.row.branch ? view.row.open : null\"\n [attr.aria-selected]=\"view.marked ? view.mark === 'all' : null\"\n [attr.aria-disabled]=\"view.disabled\"\n [style.--rt-tree-level]=\"view.row.level\"\n [rtMod]=\"{ highlighted: view.highlighted, disabled: view.disabled, chosen: view.mark === 'all' }\"\n (click)=\"onRowClick(view.row, $event)\">\n @if (view.row.branch) {\n <button\n rtElem=\"toggle\"\n qa-dataid=\"tree-row-toggle\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.row.open ? t().uiCollapse : t().uiExpand\"\n (click)=\"onToggleClick($event, view.row.option.value)\">\n <rt-icon size=\"sm\" color=\"muted\" [name]=\"view.row.open ? 'chevron-down' : 'chevron-right'\" />\n </button>\n } @else {\n <span rtElem=\"toggle-space\"></span>\n }\n\n @if (view.marked && !view.radio) {\n <rt-checkbox\n rtElem=\"check\"\n qa-dataid=\"tree-row-checkbox\"\n inert\n [disabled]=\"view.disabled\"\n [indeterminate]=\"view.mark === 'some'\"\n [ngModel]=\"view.mark === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\" />\n } @else if (view.marked) {\n <rt-radio-button\n rtElem=\"check\"\n qa-dataid=\"tree-row-radio\"\n inert\n [value]=\"view.row.option.value\"\n [checked]=\"view.mark === 'all'\"\n [disabled]=\"view.disabled\" />\n }\n\n <span rtElem=\"text\">\n <span rtElem=\"label\" qa-dataid=\"tree-row-label\" rtTooltipWhenTruncated [rtTooltip]=\"view.row.option.label\">\n @for (part of view.parts.label; track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n @if (view.parts.description.length > 0) {\n <span\n rtElem=\"description\"\n qa-dataid=\"tree-row-description\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"view.row.option.description\">\n @for (part of view.parts.description; track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n }\n @if (view.row.option.badges?.length || metaTemplate()) {\n <span rtElem=\"meta\" qa-dataid=\"tree-row-meta\">\n @for (badge of view.row.option.badges; track $index) {\n <rt-tag size=\"sm\" [value]=\"badge.text\" [severity]=\"badge.severity ?? 'neutral'\" [highlight]=\"searchTerm()\" />\n }\n @if (metaTemplate(); as meta) {\n <ng-container [ngTemplateOutlet]=\"meta\" [ngTemplateOutletContext]=\"{ $implicit: view.row.option }\" />\n }\n </span>\n }\n </span>\n\n @if (view.count) {\n <span rtElem=\"count\" qa-dataid=\"tree-row-count\">{{ view.count }}</span>\n }\n\n @if (endTemplate(); as end) {\n <span rtElem=\"end\" qa-dataid=\"tree-row-end\">\n <ng-container [ngTemplateOutlet]=\"end\" [ngTemplateOutletContext]=\"{ $implicit: view.row.option }\" />\n </span>\n }\n </div>\n } @empty {\n <div rtElem=\"empty\" qa-dataid=\"tree-empty\" [rtMod]=\"{ 'with-icon': !!emptyIcon() }\">\n @if (emptyIcon(); as icon) {\n <rt-icon rtElem=\"empty-icon\" qa-dataid=\"tree-empty-icon\" size=\"lg\" [name]=\"icon\" />\n }\n {{ emptyText() }}\n </div>\n }\n</ng-container>\n"],"mappings":"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"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-tree.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.directives.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.logic.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.component.ts","../../../projects/ui-kit-v2/src/lib/components/tree/rt-tree.component.html"],"sourcesContent":["import { inject, Directive, TemplateRef } from '@angular/core';\n\nimport { IRtTree } from './rt-tree.model';\n\n/**\n * Разметка приложения в конце каждой строки `rt-tree`. Узел строки приходит в контексте как\n * `$implicit`: дерево не заводит вход под каждый такой элемент.\n */\n@Directive({ selector: 'ng-template[rtTreeNodeEnd]' })\nexport class RtTreeNodeEndDirective<TValue> {\n public readonly templateRef: TemplateRef<IRtTree.NodeContext<TValue>> = inject<TemplateRef<IRtTree.NodeContext<TValue>>>(TemplateRef);\n}\n\n/**\n * Разметка приложения под подписью строки, в одной линии с метками узла. Узел строки приходит в\n * контексте как `$implicit`.\n */\n@Directive({ selector: 'ng-template[rtTreeNodeMeta]' })\nexport class RtTreeNodeMetaDirective<TValue> {\n public readonly templateRef: TemplateRef<IRtTree.NodeContext<TValue>> = inject<TemplateRef<IRtTree.NodeContext<TValue>>>(TemplateRef);\n}\n","import { IRtMatchPart, rtMatchParts, rtTreeBranchState, rtTreeLeaves } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTree } from './rt-tree.model';\n\n/**\n * Расчёт выбора `rt-tree` — чистые функции над неизменяемыми узлами.\n *\n * Строки, листья и отметки ветвей считает модуль дерева выбора из списка: здесь только то, чего у\n * выбора из списка нет — режим отметок, выключенный каскад и «выбрать всё». Узлы не меняются\n * никогда: каждая функция отвечает новым массивом выбора.\n */\n\ntype TNode<TValue> = IRtTree.Node<TValue>;\n\nfunction isBranch<TValue>(node: TNode<TValue>): boolean {\n return (node.children ?? []).length > 0;\n}\n\nfunction without<TValue>(value: ReadonlyArray<TValue>, drop: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return value.filter((item: TValue): boolean => !drop.includes(item));\n}\n\nfunction withAll<TValue>(value: ReadonlyArray<TValue>, add: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return [...value, ...add.filter((item: TValue): boolean => !value.includes(item))];\n}\n\n/**\n * Отметка строки. В каскаде ветка отмечена по своим листьям; без каскада и у листа — по тому,\n * лежит ли в выборе сам узел.\n */\nexport function rtTreeMark<TValue>(node: TNode<TValue>, value: ReadonlyArray<TValue>, cascade: boolean): IRtTree.Mark {\n if (cascade && isBranch(node)) {\n return rtTreeBranchState(node, value);\n }\n return value.includes(node.value) ? 'all' : 'none';\n}\n\n/**\n * Выбор после клика по узлу. Выключенный узел выбор не меняет. Одиночный режим держит один узел и\n * не снимает его повторным кликом. В каскаде ветка добавляет свои включённые листья или снимает\n * их, когда выбраны все; выключенные листья остаются как были.\n */\nexport function rtTreeChoose<TValue>(\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>,\n mode: IRtTree.Mode,\n cascade: boolean\n): ReadonlyArray<TValue> {\n if (node.disabled || mode === 'none') {\n return value;\n }\n if (mode === 'single') {\n return [node.value];\n }\n if (cascade && isBranch(node)) {\n const leaves: ReadonlyArray<TValue> = rtTreeLeaves(node);\n return rtTreeBranchState(node, value) === 'all' ? without(value, leaves) : withAll(value, leaves);\n }\n return value.includes(node.value) ? without(value, [node.value]) : withAll(value, [node.value]);\n}\n\n/**\n * Включённые листья видимых строк. Раскрытая ветка отдаёт листья своими строками ниже, свёрнутая —\n * всеми листьями под собой: они видимы через неё.\n */\nexport function rtTreeVisibleLeaves<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>): ReadonlyArray<TValue> {\n return rows.flatMap((row: IRtTree.Row<TValue>): ReadonlyArray<TValue> => (row.branch && row.open ? [] : rtTreeLeaves(row.option)));\n}\n\n/** Отметка «выбрать всё» по включённым листьям видимых строк. */\nexport function rtTreeSelectAllMark<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): IRtTree.Mark {\n const leaves: ReadonlyArray<TValue> = rtTreeVisibleLeaves(rows);\n const count: number = leaves.filter((leaf: TValue): boolean => value.includes(leaf)).length;\n if (count === 0) {\n return 'none';\n }\n return count === leaves.length ? 'all' : 'some';\n}\n\n/**\n * Выбор после клика по «выбрать всё»: включённые листья видимых строк добавляются, а когда выбраны\n * все — снимаются. Выключенные листья `rtTreeLeaves` не отдаёт, поэтому их состояние не меняется.\n */\nexport function rtTreeSelectAll<TValue>(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n const leaves: ReadonlyArray<TValue> = rtTreeVisibleLeaves(rows);\n return rtTreeSelectAllMark(rows, value) === 'all' ? without(value, leaves) : withAll(value, leaves);\n}\n\n/**\n * Подпись, описание и метки узла, разрезанные по каждому слову запроса тем же резом, что у поиска\n * меню: приложение делит поиск по пробелам, и найденное слово видно там, где оно нашлось.\n */\nexport function rtTreeLabelParts<TValue>(node: TNode<TValue>, term: string): IRtTree.LabelParts {\n return {\n label: rtMatchParts(node.label, term),\n description: rtMatchParts(node.description ?? '', term),\n badges: (node.badges ?? []).map((badge: IRtTree.Badge): ReadonlyArray<IRtMatchPart> => rtMatchParts(badge.text, term)),\n };\n}\n\n/** Значения узла и всех его потомков. */\nfunction covered<TValue>(node: TNode<TValue>): ReadonlyArray<TValue> {\n return [node.value, ...(node.children ?? []).flatMap((child: TNode<TValue>): ReadonlyArray<TValue> => covered(child))];\n}\n\n/** Значения выключенных узлов дерева: их состояние не меняет ни одно действие. */\nfunction disabledValues<TValue>(nodes: ReadonlyArray<TNode<TValue>>): ReadonlyArray<TValue> {\n return nodes.flatMap((node: TNode<TValue>): ReadonlyArray<TValue> => [\n ...(node.disabled ? [node.value] : []),\n ...disabledValues(node.children ?? []),\n ]);\n}\n\n/** Что остаётся от выбора перед кликом без Ctrl и Cmd: то, что покрывает сам узел, и выключенные узлы. */\nexport function rtTreeAloneBase<TValue>(\n nodes: ReadonlyArray<TNode<TValue>>,\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>\n): ReadonlyArray<TValue> {\n const keep: ReadonlyArray<TValue> = [...covered(node), ...disabledValues(nodes)];\n return value.filter((item: TValue): boolean => keep.includes(item));\n}\n\n/**\n * Выбор после клика без Ctrl и Cmd в режиме, где клик выбирает один узел. Из выбора остаётся только\n * то, что покрывает сам узел, и выключенные узлы; дальше клик работает как обычно — поэтому\n * повторный клик по единственному выбранному снимает его.\n */\nexport function rtTreeChooseAlone<TValue>(\n nodes: ReadonlyArray<TNode<TValue>>,\n node: TNode<TValue>,\n value: ReadonlyArray<TValue>,\n cascade: boolean\n): ReadonlyArray<TValue> {\n if (node.disabled) {\n return value;\n }\n return rtTreeChoose(node, rtTreeAloneBase(nodes, node, value), 'multiple', cascade);\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n contentChild,\n inject,\n input,\n model,\n output,\n signal,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n ModelSignal,\n OutputEmitterRef,\n Signal,\n TemplateRef,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon, RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtCheckboxComponent } from '@rt-tools/ui-kit-v2/checkbox';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtRadioButtonComponent } from '@rt-tools/ui-kit-v2/radio-button';\nimport { RtTagComponent } from '@rt-tools/ui-kit-v2/tag';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { IRtOptionTree, rtTreeOpenFor, rtTreeRows, rtTreeSideKey, rtTreeToggle } from '@rt-tools/ui-kit-v2/core';\nimport { RtTreeNodeEndDirective, RtTreeNodeMetaDirective } from './rt-tree.directives';\nimport { rtTreeChoose, rtTreeChooseAlone, rtTreeLabelParts, rtTreeMark, rtTreeSelectAll, rtTreeSelectAllMark } from './rt-tree.logic';\nimport { IRtTree } from './rt-tree.model';\n\nconst BEM_BLOCK: string = 'rt-tree';\n\n/** Видимая строка с тем, что разметке нужно о ней знать. */\ninterface IRtTreeView<TValue> {\n readonly row: IRtTree.Row<TValue>;\n readonly mark: IRtTree.Mark;\n /** Рисуется ли у строки флажок или радио: у групп без отметок его нет. */\n readonly marked: boolean;\n /** Радио вместо флажка. */\n readonly radio: boolean;\n /** Строка выключена: свой `disabled` у узла или выключено всё дерево. */\n readonly disabled: boolean;\n /** Число выбранного под группой в конце строки; `null` — числа нет. */\n readonly count: number | null;\n readonly parts: IRtTree.LabelParts;\n readonly highlighted: boolean;\n}\n\n/**\n * Дерево выбора, стоящее на странице само по себе.\n *\n * Строки, листья, отметки ветвей, отбор по слову и боковые стрелки считает модуль дерева выбора\n * из списка — тот же, что у `rt-select` и `rt-multiselect`. Выбор живёт в `value`; узлы не\n * меняются. Раскрытые ветки и подсвеченная строка — состояние самого дерева.\n *\n * Клавиатура идёт через `handleKeydown`: его зовёт и само дерево с фокуса на себе, и приложение\n * со своего поля поиска. Ответ — взята ли клавиша: чужую дерево не трогает.\n */\n@Component({\n selector: 'rt-tree',\n templateUrl: './rt-tree.component.html',\n styleUrl: './rt-tree.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n NgTemplateOutlet,\n FormsModule,\n RtCheckboxComponent,\n RtIconComponent,\n RtRadioButtonComponent,\n RtTagComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n role: 'tree',\n '[attr.tabindex]': 'disabled() ? -1 : 0',\n '[attr.aria-disabled]': 'disabled() || null',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-multiselectable]': \"mode() === 'multiple'\",\n '(keydown)': 'handleKeydown($event)',\n },\n})\nexport class RtTreeComponent<TValue> {\n readonly #open: WritableSignal<ReadonlySet<TValue> | null> = signal<ReadonlySet<TValue> | null>(null);\n readonly #highlighted: WritableSignal<TValue | null> = signal<TValue | null>(null);\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly nodeEnd: Signal<RtTreeNodeEndDirective<TValue> | undefined> = contentChild(RtTreeNodeEndDirective);\n\n protected readonly nodeMeta: Signal<RtTreeNodeMetaDirective<TValue> | undefined> = contentChild(RtTreeNodeMetaDirective);\n\n /** Разметка в конце строки: вход раньше директивы — обёртка вроде селектора отдаёт её входом. */\n protected readonly endTemplate: Signal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = computed(\n (): TemplateRef<IRtTree.NodeContext<TValue>> | null => this.nodeEndTemplate() ?? this.nodeEnd()?.templateRef ?? null\n );\n\n /** Разметка под подписью: вход раньше директивы. */\n protected readonly metaTemplate: Signal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = computed(\n (): TemplateRef<IRtTree.NodeContext<TValue>> | null => this.nodeMetaTemplate() ?? this.nodeMeta()?.templateRef ?? null\n );\n\n /** Раскрытые ветки: до первого действия человека — ветки над выбранным. */\n protected readonly openBranches: Signal<ReadonlySet<TValue>> = computed(\n (): ReadonlySet<TValue> => this.#open() ?? rtTreeOpenFor(this.nodes(), this.value())\n );\n\n protected readonly rows: Signal<ReadonlyArray<IRtTree.Row<TValue>>> = computed((): ReadonlyArray<IRtTree.Row<TValue>> =>\n rtTreeRows(this.nodes(), this.openBranches(), this.filter() ? this.searchTerm() : '')\n );\n\n protected readonly views: Signal<ReadonlyArray<IRtTreeView<TValue>>> = computed((): ReadonlyArray<IRtTreeView<TValue>> => {\n const value: ReadonlyArray<TValue> = this.value();\n const cascade: boolean = this.cascade();\n const term: string = this.searchTerm();\n const highlighted: TValue | null = this.#highlighted();\n const mode: IRtTree.Mode = this.mode();\n const branchMarks: boolean = this.branchMarks();\n const treeDisabled: boolean = this.disabled();\n return this.rows().map((row: IRtTree.Row<TValue>): IRtTreeView<TValue> => {\n const marked: boolean = mode !== 'none' && (branchMarks || !row.branch);\n const state: IRtTree.RowState = this.rowState(row, value, cascade);\n return {\n row,\n marked,\n mark: state.mark,\n radio: state.radio,\n disabled: treeDisabled || !!row.option.disabled,\n count: marked ? null : state.count,\n parts: rtTreeLabelParts(row.option, term),\n highlighted: row.option.value === highlighted,\n };\n });\n });\n\n protected readonly selectAllMark: Signal<IRtTree.Mark> = computed((): IRtTree.Mark => this.selectAllMarkOf(this.rows(), this.value()));\n\n protected readonly isSelectAllShown: Signal<boolean> = computed(\n (): boolean => this.showSelectAll() && this.cascade() && this.mode() === 'multiple' && this.rows().length > 0\n );\n\n /** Отметка «выбрать всё» встаёт над отметкой первой строки; у строки без отметки — над стрелкой. */\n protected readonly isSelectAllUnderMark: Signal<boolean> = computed((): boolean => this.views()[0]?.marked ?? false);\n\n /** Первая строка — лист: там, где у листа нет места под стрелку, его нет и у «выбрать всё». */\n protected readonly isSelectAllOverLeaf: Signal<boolean> = computed((): boolean => this.views()[0]?.row.branch === false);\n\n protected readonly emptyText: Signal<string> = computed((): string =>\n this.nodes().length > 0 ? this.t().uiNothingFound : this.t().uiNoOptions\n );\n\n public readonly nodes: InputSignal<ReadonlyArray<IRtTree.Node<TValue>>> = input.required<ReadonlyArray<IRtTree.Node<TValue>>>();\n public readonly value: ModelSignal<ReadonlyArray<TValue>> = model<ReadonlyArray<TValue>>([]);\n public readonly mode: InputSignal<IRtTree.Mode> = input<IRtTree.Mode>('multiple');\n public readonly cascade: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, { transform: booleanAttribute });\n public readonly searchTerm: InputSignal<string> = input<string>('');\n public readonly showSelectAll: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n public readonly ariaLabel: InputSignal<string | null> = input<string | null>(null);\n\n /** Отметки у групп. Без них клик, пробел и Enter по группе раскрывают и сворачивают её. */\n public readonly branchMarks: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, {\n transform: booleanAttribute,\n });\n\n /** Клик без Ctrl и Cmd выбирает узел один; с Ctrl или Cmd добавляет к выбору. Только для флажков. */\n public readonly exclusive: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n /** Скрывает ли слово поиска строки. Без отбора строки отбирает приложение, а слово только отмечено. */\n public readonly filter: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(true, {\n transform: booleanAttribute,\n });\n\n /** Выключенное дерево не меняет выбор ни кликом, ни клавишей, ни «выбрать всё»; ветки раскрываются стрелкой. */\n /** Значок кита над подписью пустого дерева. Без него пустое дерево — одна подпись. */\n public readonly emptyIcon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /**\n * Разметка в конце каждой строки, отданная входом. Нужна компоненту, который оборачивает дерево и\n * не может положить в него директиву `rtTreeNodeEnd`; вход сильнее директивы.\n */\n public readonly nodeEndTemplate: InputSignal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = input<TemplateRef<\n IRtTree.NodeContext<TValue>\n > | null>(null);\n\n /** Разметка под подписью каждой строки, отданная входом; вход сильнее директивы `rtTreeNodeMeta`. */\n public readonly nodeMetaTemplate: InputSignal<TemplateRef<IRtTree.NodeContext<TValue>> | null> = input<TemplateRef<\n IRtTree.NodeContext<TValue>\n > | null>(null);\n\n public readonly disabled: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n public readonly picked: OutputEmitterRef<IRtTree.Node<TValue>> = output<IRtTree.Node<TValue>>();\n\n /**\n * Клавиша для дерева. Отвечает, взята ли она: не взятая идёт дальше нетронутой, поэтому\n * приложение может отдавать сюда каждую клавишу своего поля поиска.\n */\n public handleKeydown(event: KeyboardEvent): boolean {\n if (this.disabled()) {\n return false;\n }\n const taken: boolean = this.#takeKey(event.key, event.ctrlKey || event.metaKey);\n if (taken) {\n event.preventDefault();\n event.stopPropagation();\n }\n return taken;\n }\n\n public expandAll(): void {\n const all: Set<TValue> = new Set<TValue>();\n this.#collectBranches(this.nodes(), all);\n this.#open.set(all);\n }\n\n public collapseAll(): void {\n this.#open.set(new Set<TValue>());\n }\n\n public clearHighlight(): void {\n this.#highlighted.set(null);\n }\n\n protected onRowClick(row: IRtTree.Row<TValue>, event: MouseEvent): void {\n if (this.disabled()) {\n return;\n }\n this.#highlighted.set(row.option.value);\n if (row.option.disabled) {\n return;\n }\n if (this.#opensOnly(row)) {\n this.#toggleOrPick(row);\n return;\n }\n this.#choose(this.nextChoice(row.option, event.ctrlKey || event.metaKey));\n }\n\n protected onToggleClick(event: Event, value: TValue): void {\n event.stopPropagation();\n this.#toggle(value);\n }\n\n protected onSelectAll(): void {\n if (this.disabled()) {\n return;\n }\n this.#choose(this.selectAllChoice(this.rows(), this.value()));\n }\n\n /**\n * Отметка строки, её вид и число выбранного под ней. Дерево числа не рисует; наследник со своими\n * правилами выбора считает всё это по ним.\n */\n protected rowState(row: IRtTree.Row<TValue>, value: ReadonlyArray<TValue>, cascade: boolean): IRtTree.RowState {\n return { mark: rtTreeMark(row.option, value, cascade), radio: this.mode() === 'single', count: null };\n }\n\n protected selectAllMarkOf(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): IRtTree.Mark {\n return rtTreeSelectAllMark(rows, value);\n }\n\n protected selectAllChoice(rows: ReadonlyArray<IRtTree.Row<TValue>>, value: ReadonlyArray<TValue>): ReadonlyArray<TValue> {\n return rtTreeSelectAll(rows, value);\n }\n\n /** Выбор после действия над узлом: в исключающем режиме без Ctrl и Cmd узел остаётся один. */\n protected nextChoice(node: IRtTree.Node<TValue>, additive: boolean): ReadonlyArray<TValue> {\n if (this.exclusive() && this.mode() === 'multiple' && !additive) {\n return rtTreeChooseAlone(this.nodes(), node, this.value(), this.cascade());\n }\n return rtTreeChoose(node, this.value(), this.mode(), this.cascade());\n }\n\n /** Строка, клик по которой ничего не отмечает: режим без отметок или группа без флажка. */\n #opensOnly(row: IRtTree.Row<TValue>): boolean {\n return this.mode() === 'none' || (row.branch && !this.branchMarks());\n }\n\n #toggleOrPick(row: IRtTree.Row<TValue>): void {\n if (row.branch) {\n this.#toggle(row.option.value);\n } else {\n this.picked.emit(row.option);\n }\n }\n\n #collectBranches(list: ReadonlyArray<IRtTree.Node<TValue>>, into: Set<TValue>): void {\n list.forEach((node: IRtTree.Node<TValue>): void => {\n if ((node.children ?? []).length > 0) {\n into.add(node.value);\n this.#collectBranches(node.children ?? [], into);\n }\n });\n }\n\n /**\n * Меняет выбор, не трогая раскрытие. Пока ветки никто не раскрывал руками, раскрытие считается из\n * выбора, и без этой фиксации отметка ветки сворачивала или раскрывала её саму.\n */\n #choose(next: ReadonlyArray<TValue>): void {\n this.#open.set(this.openBranches());\n this.value.set(next);\n }\n\n #toggle(value: TValue): void {\n this.#open.set(rtTreeToggle(this.openBranches(), value));\n }\n\n #highlightedIndex(): number {\n const highlighted: TValue | null = this.#highlighted();\n return this.rows().findIndex((row: IRtTree.Row<TValue>): boolean => row.option.value === highlighted);\n }\n\n #takeKey(key: string, additive: boolean): boolean {\n const rows: ReadonlyArray<IRtTree.Row<TValue>> = this.rows();\n const index: number = this.#highlightedIndex();\n if (key === 'ArrowDown' || key === 'ArrowUp') {\n return this.#move(rows, index, key === 'ArrowDown' ? 1 : -1);\n }\n return index >= 0 && this.#takeRowKey(rows, index, key, additive);\n }\n\n /** Клавиши, которым нужна подсвеченная строка. */\n #takeRowKey(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, key: string, additive: boolean): boolean {\n if (key === 'Home' || key === 'End') {\n return this.#edge(rows, key);\n }\n if (key === 'ArrowRight' || key === 'ArrowLeft') {\n this.#side(rows, index, key);\n return true;\n }\n if (key === ' ') {\n this.#space(rows[index], additive);\n return true;\n }\n if (key === 'Enter') {\n this.#enter(rows[index], additive);\n return true;\n }\n return false;\n }\n\n #move(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, step: number): boolean {\n if (rows.length === 0) {\n return false;\n }\n const next: number = index < 0 ? 0 : Math.min(rows.length - 1, Math.max(0, index + step));\n this.#highlighted.set(rows[next].option.value);\n return true;\n }\n\n /** Home и End ведут подсветку к первой и последней строке; без подсветки они остаются у курсора поля. */\n #edge(rows: ReadonlyArray<IRtTree.Row<TValue>>, key: string): boolean {\n this.#highlighted.set(rows[key === 'Home' ? 0 : rows.length - 1].option.value);\n return true;\n }\n\n #side(rows: ReadonlyArray<IRtTree.Row<TValue>>, index: number, key: string): void {\n const answer: IRtOptionTree.SideKeyAnswer<TValue> = rtTreeSideKey(rows, index, key);\n if (answer.toggle !== null) {\n this.#toggle(answer.toggle);\n }\n this.#highlighted.set(rows[answer.index].option.value);\n }\n\n #space(row: IRtTree.Row<TValue>, additive: boolean): void {\n if (this.#opensOnly(row) && row.branch) {\n this.#toggle(row.option.value);\n return;\n }\n if (!row.option.disabled && this.mode() !== 'none') {\n this.#choose(this.nextChoice(row.option, additive));\n }\n }\n\n #enter(row: IRtTree.Row<TValue>, additive: boolean): void {\n if (this.#opensOnly(row) && row.branch) {\n this.#toggle(row.option.value);\n return;\n }\n if (row.option.disabled) {\n return;\n }\n if (this.mode() !== 'none') {\n this.#choose(this.nextChoice(row.option, additive));\n }\n this.picked.emit(row.option);\n }\n}\n","<ng-container rtBlock=\"rt-tree\">\n <!--\n Строки выбираются мышью через (click); клавиатура — на самом дереве (handleKeydown), строки\n по отдельности фокус не берут: подсветка — третье состояние рядом с фокусом и выбором.\n -->\n <!-- eslint-disable @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n @if (isSelectAllShown()) {\n <div\n rtElem=\"select-all\"\n qa-dataid=\"tree-select-all\"\n role=\"presentation\"\n [rtMod]=\"{ disabled: disabled(), 'over-leaf': isSelectAllOverLeaf() }\"\n (click)=\"onSelectAll()\">\n @if (isSelectAllUnderMark()) {\n <span rtElem=\"toggle-space\"></span>\n }\n <rt-checkbox\n rtElem=\"check\"\n inert\n [disabled]=\"disabled()\"\n [indeterminate]=\"selectAllMark() === 'some'\"\n [ngModel]=\"selectAllMark() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\" />\n <span rtElem=\"label\">{{ t().uiSelectAll }}</span>\n </div>\n }\n\n @for (view of views(); track view.row.option.value) {\n <div\n rtElem=\"row\"\n qa-dataid=\"tree-row\"\n role=\"treeitem\"\n [attr.data-value]=\"view.row.option.value\"\n [attr.aria-level]=\"view.row.level + 1\"\n [attr.aria-expanded]=\"view.row.branch ? view.row.open : null\"\n [attr.aria-selected]=\"view.marked ? view.mark === 'all' : null\"\n [attr.aria-disabled]=\"view.disabled\"\n [style.--rt-tree-level]=\"view.row.level\"\n [rtMod]=\"{ highlighted: view.highlighted, disabled: view.disabled, chosen: view.mark === 'all' }\"\n (click)=\"onRowClick(view.row, $event)\">\n @if (view.row.branch) {\n <button\n rtElem=\"toggle\"\n qa-dataid=\"tree-row-toggle\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"view.row.open ? t().uiCollapse : t().uiExpand\"\n (click)=\"onToggleClick($event, view.row.option.value)\">\n <rt-icon size=\"sm\" color=\"muted\" [name]=\"view.row.open ? 'chevron-down' : 'chevron-right'\" />\n </button>\n } @else {\n <span rtElem=\"toggle-space\"></span>\n }\n\n @if (view.marked && !view.radio) {\n <rt-checkbox\n rtElem=\"check\"\n qa-dataid=\"tree-row-checkbox\"\n inert\n [disabled]=\"view.disabled\"\n [indeterminate]=\"view.mark === 'some'\"\n [ngModel]=\"view.mark === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\" />\n } @else if (view.marked) {\n <rt-radio-button\n rtElem=\"check\"\n qa-dataid=\"tree-row-radio\"\n inert\n [value]=\"view.row.option.value\"\n [checked]=\"view.mark === 'all'\"\n [disabled]=\"view.disabled\" />\n }\n\n <span rtElem=\"text\">\n <span rtElem=\"label\" qa-dataid=\"tree-row-label\" rtTooltipWhenTruncated [rtTooltip]=\"view.row.option.label\">\n @for (part of view.parts.label; track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n @if (view.parts.description.length > 0) {\n <span\n rtElem=\"description\"\n qa-dataid=\"tree-row-description\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"view.row.option.description\">\n @for (part of view.parts.description; track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n }\n @if (view.row.option.badges?.length || metaTemplate()) {\n <span rtElem=\"meta\" qa-dataid=\"tree-row-meta\">\n @for (badge of view.row.option.badges; track $index) {\n <rt-tag size=\"sm\" [value]=\"badge.text\" [severity]=\"badge.severity ?? 'neutral'\" [highlight]=\"searchTerm()\" />\n }\n @if (metaTemplate(); as meta) {\n <ng-container [ngTemplateOutlet]=\"meta\" [ngTemplateOutletContext]=\"{ $implicit: view.row.option }\" />\n }\n </span>\n }\n </span>\n\n @if (view.count) {\n <span rtElem=\"count\" qa-dataid=\"tree-row-count\">{{ view.count }}</span>\n }\n\n @if (endTemplate(); as end) {\n <span rtElem=\"end\" qa-dataid=\"tree-row-end\">\n <ng-container [ngTemplateOutlet]=\"end\" [ngTemplateOutletContext]=\"{ $implicit: view.row.option }\" />\n </span>\n }\n </div>\n } @empty {\n <div rtElem=\"empty\" qa-dataid=\"tree-empty\" [rtMod]=\"{ 'with-icon': !!emptyIcon() }\">\n @if (emptyIcon(); as icon) {\n <rt-icon rtElem=\"empty-icon\" qa-dataid=\"tree-empty-icon\" size=\"lg\" [name]=\"icon\" />\n }\n {{ emptyText() }}\n </div>\n }\n</ng-container>\n"],"mappings":"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"}
@@ -0,0 +1,164 @@
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 rtTooltipShowOnTap\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
+ "rtTooltipShowOnTap"
104
+ ],
105
+ exportAs: ["rtTooltip"]
106
+ }
107
+ ],
108
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
109
+ encapsulation: i0.ViewEncapsulation.None
110
+ });
111
+ }
112
+ };
113
+ i0.ɵɵngDeclareClassMetadata({
114
+ minVersion: "12.0.0",
115
+ version: "22.2.2",
116
+ ngImport: i0,
117
+ type: RtUsageRingComponent,
118
+ decorators: [{
119
+ type: Component,
120
+ args: [{
121
+ selector: "rt-usage-ring",
122
+ changeDetection: ChangeDetectionStrategy.OnPush,
123
+ encapsulation: ViewEncapsulation.None,
124
+ imports: [
125
+ BlockDirective,
126
+ ElemDirective,
127
+ ModDirective,
128
+ RtTooltipDirective
129
+ ],
130
+ host: { class: BEM_BLOCK },
131
+ template: "<ng-container rtBlock=\"rt-usage-ring\">\n <span\n rtElem=\"ring\"\n role=\"img\"\n qa-dataid=\"usage-ring\"\n rtTooltipShowOnTap\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",
132
+ 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"]
133
+ }]
134
+ }],
135
+ propDecorators: {
136
+ value: [{
137
+ type: i0.Input,
138
+ args: [{
139
+ isSignal: true,
140
+ alias: "value",
141
+ required: false
142
+ }]
143
+ }],
144
+ warnAt: [{
145
+ type: i0.Input,
146
+ args: [{
147
+ isSignal: true,
148
+ alias: "warnAt",
149
+ required: false
150
+ }]
151
+ }],
152
+ hint: [{
153
+ type: i0.Input,
154
+ args: [{
155
+ isSignal: true,
156
+ alias: "hint",
157
+ required: false
158
+ }]
159
+ }]
160
+ }
161
+ });
162
+ export { RT_USAGE_RING_CIRCUMFERENCE, RtUsageRingComponent, rtUsagePercent };
163
+
164
+ //# 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 rtTooltipShowOnTap\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.34.5",
3
+ "version": "0.35.1",
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`: поле переписки с людьми, капсула и форматирование.