@rt-tools/ui-kit-v2 0.29.0 → 0.30.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.
Files changed (63) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +23 -29
  2. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +2 -2
  4. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +223 -3
  6. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +2 -2
  8. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +1 -2
  10. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +2 -2
  12. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +277 -904
  14. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +2 -2
  16. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +1 -1
  18. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +35 -48
  20. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +2 -2
  22. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs +2 -2
  23. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs.map +1 -1
  24. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +4 -0
  25. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -1
  26. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +4 -4
  27. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +37 -181
  29. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
  30. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +5 -36
  31. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
  32. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +4 -1
  33. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  34. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +2 -3
  35. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  36. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +2 -2
  37. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -1
  38. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +8 -13
  39. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
  40. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +12 -7
  41. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
  42. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +2 -2
  43. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  44. package/package.json +1 -1
  45. package/src/lib/components/dynamic-selector/stories/component/test-dynamic-selector-popup-frame.component.scss +6 -0
  46. package/src/lib/components/page-header/rt-page-header.component.scss +4 -2
  47. package/src/lib/components/popover/CONTEXT.md +2 -1
  48. package/src/lib/components/tree/CONTEXT.md +1 -1
  49. package/src/rich-editor/lib/components/ai-chat/CONTEXT.md +1 -1
  50. package/src/styles/_breakpoints.scss +37 -4
  51. package/src/styles/_index.scss +0 -4
  52. package/styles/tokens.css +0 -8
  53. package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +4 -3
  54. package/types/rt-tools-ui-kit-v2-core.d.ts +155 -1
  55. package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +51 -269
  56. package/types/rt-tools-ui-kit-v2-multiselect.d.ts +4 -3
  57. package/types/rt-tools-ui-kit-v2-select.d.ts +12 -74
  58. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +5 -20
  59. package/types/rt-tools-ui-kit-v2-table.d.ts +4 -0
  60. package/types/rt-tools-ui-kit-v2-tag.d.ts +2 -3
  61. package/types/rt-tools-ui-kit-v2-tree-selector.d.ts +0 -2
  62. package/types/rt-tools-ui-kit-v2-tree.d.ts +7 -9
  63. package/src/styles/_place.scss +0 -7
@@ -1,9 +1,9 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injector, TemplateRef, ViewEncapsulation, afterNextRender, booleanAttribute, computed, contentChild, forwardRef, inject, input, model, output, signal, viewChild, viewChildren } from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injectable, Injector, TemplateRef, ViewEncapsulation, afterNextRender, booleanAttribute, computed, contentChild, forwardRef, inject, input, model, output, signal, viewChild, viewChildren } from "@angular/core";
3
3
  import * as i1 from "@angular/forms";
4
4
  import { FormsModule } from "@angular/forms";
5
5
  import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
6
- import { BreakpointsService, RtInfiniteScrollDirective, rtKitDefault, rtKitLabel } from "@rt-tools/ui-kit-v2/core";
6
+ import { BreakpointsService, RtInfiniteScrollDirective, RtOptionList, rtKitDefault, rtKitLabel, rtMatchParts, rtSearchMatches } from "@rt-tools/ui-kit-v2/core";
7
7
  import { RtButtonDirective } from "@rt-tools/ui-kit-v2/button";
8
8
  import { RtEmptyStateComponent } from "@rt-tools/ui-kit-v2/empty-state";
9
9
  import { RtFormControlBase } from "@rt-tools/ui-kit-v2/form-control";
@@ -22,10 +22,54 @@ import { RtRadioButtonComponent } from "@rt-tools/ui-kit-v2/radio-button";
22
22
  import { RtSpinnerComponent } from "@rt-tools/ui-kit-v2/spinner";
23
23
  import { RtToggleSwitchComponent } from "@rt-tools/ui-kit-v2/toggle-switch";
24
24
  import { RtPopoverDirective } from "@rt-tools/ui-kit-v2/popover";
25
+ var RtDynamicSelectorPartsService = class RtDynamicSelectorPartsService {
26
+ #popup = null;
27
+ #list = null;
28
+ get popup() {
29
+ if (this.#popup === null) throw new Error("rt-dynamic-selector-popup стоит вне корня: источник окна не привязан");
30
+ return this.#popup;
31
+ }
32
+ get list() {
33
+ if (this.#list === null) throw new Error("rt-dynamic-selector-list стоит вне корня: источник списка не привязан");
34
+ return this.#list;
35
+ }
36
+ bindPopup(source) {
37
+ this.#popup = source;
38
+ }
39
+ bindList(source) {
40
+ this.#list = source;
41
+ }
42
+ static {
43
+ this.ɵfac = i0.ɵɵngDeclareFactory({
44
+ minVersion: "12.0.0",
45
+ version: "22.2.2",
46
+ ngImport: i0,
47
+ type: RtDynamicSelectorPartsService,
48
+ deps: [],
49
+ target: i0.ɵɵFactoryTarget.Injectable
50
+ });
51
+ }
52
+ static {
53
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
54
+ minVersion: "12.0.0",
55
+ version: "22.2.2",
56
+ ngImport: i0,
57
+ type: RtDynamicSelectorPartsService
58
+ });
59
+ }
60
+ };
61
+ i0.ɵɵngDeclareClassMetadata({
62
+ minVersion: "12.0.0",
63
+ version: "22.2.2",
64
+ ngImport: i0,
65
+ type: RtDynamicSelectorPartsService,
66
+ decorators: [{ type: Injectable }]
67
+ });
25
68
  const BEM_BLOCK$3 = "rt-dynamic-selector-list";
26
69
  var RtDynamicSelectorListComponent = class RtDynamicSelectorListComponent {
27
70
  constructor() {
28
71
  this.#breakpoints = inject(BreakpointsService);
72
+ this.#source = inject(RtDynamicSelectorPartsService).list;
29
73
  this.isNarrow = this.#breakpoints.viewportNarrow;
30
74
  this.dragLabel = rtKitLabel("dynamicSelectorDrag");
31
75
  this.removeLabel = rtKitLabel("dynamicSelectorRemove");
@@ -36,70 +80,39 @@ var RtDynamicSelectorListComponent = class RtDynamicSelectorListComponent {
36
80
  this.clearLabel = rtKitLabel("dynamicSelectorClear");
37
81
  this.editedIndex = signal(null, ...ngDevMode ? [{ debugName: "editedIndex" }] : /* istanbul ignore next */ []);
38
82
  this.draft = signal("", ...ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []);
39
- this.rows = input([], ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
40
- this.draggable = input(false, {
41
- ...ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {},
42
- transform: booleanAttribute
43
- });
44
- this.editable = input(false, {
45
- ...ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {},
46
- transform: booleanAttribute
47
- });
48
- this.disabled = input(false, {
49
- ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
50
- transform: booleanAttribute
51
- });
52
- this.actionsShown = input(true, {
53
- ...ngDevMode ? { debugName: "actionsShown" } : /* istanbul ignore next */ {},
54
- transform: booleanAttribute
55
- });
56
- this.resetClearShown = input(true, {
57
- ...ngDevMode ? { debugName: "resetClearShown" } : /* istanbul ignore next */ {},
58
- transform: booleanAttribute
59
- });
60
- this.removeShown = input(true, {
61
- ...ngDevMode ? { debugName: "removeShown" } : /* istanbul ignore next */ {},
62
- transform: booleanAttribute
63
- });
64
- this.resetDisabled = input(true, {
65
- ...ngDevMode ? { debugName: "resetDisabled" } : /* istanbul ignore next */ {},
66
- transform: booleanAttribute
67
- });
68
- this.clearDisabled = input(true, {
69
- ...ngDevMode ? { debugName: "clearDisabled" } : /* istanbul ignore next */ {},
70
- transform: booleanAttribute
71
- });
72
- this.buttonRadius = input("full", ...ngDevMode ? [{ debugName: "buttonRadius" }] : /* istanbul ignore next */ []);
73
- this.clearIcon = input("close", ...ngDevMode ? [{ debugName: "clearIcon" }] : /* istanbul ignore next */ []);
74
- this.titleWrap = input(true, {
75
- ...ngDevMode ? { debugName: "titleWrap" } : /* istanbul ignore next */ {},
76
- transform: booleanAttribute
77
- });
78
- this.titleTpl = input(null, ...ngDevMode ? [{ debugName: "titleTpl" }] : /* istanbul ignore next */ []);
79
- this.controlsTpl = input(null, ...ngDevMode ? [{ debugName: "controlsTpl" }] : /* istanbul ignore next */ []);
80
- this.removed = output();
81
- this.moved = output();
82
- this.edited = output();
83
- this.resetClicked = output();
84
- this.cleared = output();
83
+ this.rows = this.#source.rows;
84
+ this.draggable = this.#source.draggable;
85
+ this.editable = this.#source.editable;
86
+ this.disabled = this.#source.disabled;
87
+ this.actionsShown = this.#source.actionsShown;
88
+ this.resetClearShown = this.#source.resetClearShown;
89
+ this.removeShown = this.#source.removeShown;
90
+ this.resetDisabled = this.#source.resetDisabled;
91
+ this.clearDisabled = this.#source.clearDisabled;
92
+ this.buttonRadius = this.#source.buttonRadius;
93
+ this.clearIcon = this.#source.clearIcon;
94
+ this.titleWrap = this.#source.titleWrap;
95
+ this.titleTpl = this.#source.titleTpl;
96
+ this.controlsTpl = this.#source.controlsTpl;
85
97
  }
86
98
  #breakpoints;
99
+ #source;
87
100
  onDrop(event) {
88
101
  if (event.previousContainer !== event.container || event.previousIndex === event.currentIndex) return;
89
- this.moved.emit({
102
+ this.#source.move({
90
103
  from: event.previousIndex,
91
104
  to: event.currentIndex
92
105
  });
93
106
  }
94
107
  onRemove(row) {
95
- if (!row.locked && !this.disabled()) this.removed.emit(row.key);
108
+ if (!row.locked && !this.disabled()) this.#source.remove(row.key);
96
109
  }
97
110
  onEditStart(index, row) {
98
111
  this.draft.set(row.label);
99
112
  this.editedIndex.set(index);
100
113
  }
101
114
  onEditApply(row) {
102
- this.edited.emit({
115
+ this.#source.edit({
103
116
  previous: row.label,
104
117
  next: this.draft()
105
118
  });
@@ -108,6 +121,12 @@ var RtDynamicSelectorListComponent = class RtDynamicSelectorListComponent {
108
121
  onEditCancel() {
109
122
  this.editedIndex.set(null);
110
123
  }
124
+ onReset() {
125
+ this.#source.reset();
126
+ }
127
+ onClear() {
128
+ this.#source.clear();
129
+ }
111
130
  static {
112
131
  this.ɵfac = i0.ɵɵngDeclareFactory({
113
132
  minVersion: "12.0.0",
@@ -125,116 +144,9 @@ var RtDynamicSelectorListComponent = class RtDynamicSelectorListComponent {
125
144
  type: RtDynamicSelectorListComponent,
126
145
  isStandalone: true,
127
146
  selector: "rt-dynamic-selector-list",
128
- inputs: {
129
- rows: {
130
- classPropertyName: "rows",
131
- publicName: "rows",
132
- isSignal: true,
133
- isRequired: false,
134
- transformFunction: null
135
- },
136
- draggable: {
137
- classPropertyName: "draggable",
138
- publicName: "draggable",
139
- isSignal: true,
140
- isRequired: false,
141
- transformFunction: null
142
- },
143
- editable: {
144
- classPropertyName: "editable",
145
- publicName: "editable",
146
- isSignal: true,
147
- isRequired: false,
148
- transformFunction: null
149
- },
150
- disabled: {
151
- classPropertyName: "disabled",
152
- publicName: "disabled",
153
- isSignal: true,
154
- isRequired: false,
155
- transformFunction: null
156
- },
157
- actionsShown: {
158
- classPropertyName: "actionsShown",
159
- publicName: "actionsShown",
160
- isSignal: true,
161
- isRequired: false,
162
- transformFunction: null
163
- },
164
- resetClearShown: {
165
- classPropertyName: "resetClearShown",
166
- publicName: "resetClearShown",
167
- isSignal: true,
168
- isRequired: false,
169
- transformFunction: null
170
- },
171
- removeShown: {
172
- classPropertyName: "removeShown",
173
- publicName: "removeShown",
174
- isSignal: true,
175
- isRequired: false,
176
- transformFunction: null
177
- },
178
- resetDisabled: {
179
- classPropertyName: "resetDisabled",
180
- publicName: "resetDisabled",
181
- isSignal: true,
182
- isRequired: false,
183
- transformFunction: null
184
- },
185
- clearDisabled: {
186
- classPropertyName: "clearDisabled",
187
- publicName: "clearDisabled",
188
- isSignal: true,
189
- isRequired: false,
190
- transformFunction: null
191
- },
192
- buttonRadius: {
193
- classPropertyName: "buttonRadius",
194
- publicName: "buttonRadius",
195
- isSignal: true,
196
- isRequired: false,
197
- transformFunction: null
198
- },
199
- clearIcon: {
200
- classPropertyName: "clearIcon",
201
- publicName: "clearIcon",
202
- isSignal: true,
203
- isRequired: false,
204
- transformFunction: null
205
- },
206
- titleWrap: {
207
- classPropertyName: "titleWrap",
208
- publicName: "titleWrap",
209
- isSignal: true,
210
- isRequired: false,
211
- transformFunction: null
212
- },
213
- titleTpl: {
214
- classPropertyName: "titleTpl",
215
- publicName: "titleTpl",
216
- isSignal: true,
217
- isRequired: false,
218
- transformFunction: null
219
- },
220
- controlsTpl: {
221
- classPropertyName: "controlsTpl",
222
- publicName: "controlsTpl",
223
- isSignal: true,
224
- isRequired: false,
225
- transformFunction: null
226
- }
227
- },
228
- outputs: {
229
- removed: "removed",
230
- moved: "moved",
231
- edited: "edited",
232
- resetClicked: "resetClicked",
233
- cleared: "cleared"
234
- },
235
147
  host: { classAttribute: "rt-dynamic-selector-list" },
236
148
  ngImport: i0,
237
- template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span\n rtElem=\"title\"\n rtTooltipWhenTruncated\n [rtMod]=\"{ nowrap: !titleWrap() }\"\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n {{ row.label }}\n </span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n rtElem=\"reset\"\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"resetClicked.emit()\" />\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"dynamic-selector-clear\"\n size=\"sm\"\n [icon]=\"clearIcon()\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"cleared.emit()\" />\n }\n </div>\n }\n</ng-container>\n",
149
+ template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span\n rtElem=\"title\"\n rtTooltipWhenTruncated\n [rtMod]=\"{ nowrap: !titleWrap() }\"\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n {{ row.label }}\n </span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n rtElem=\"reset\"\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"onReset()\" />\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"dynamic-selector-clear\"\n size=\"sm\"\n [icon]=\"clearIcon()\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"onClear()\" />\n }\n </div>\n }\n</ng-container>\n",
238
150
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-list{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-drag-duration: var(--rt-duration-base);--rt-dynamic-selector-list-row-padding-x: var(--rt-space-sm);--rt-dynamic-selector-list-add-font-weight: var(--rt-font-weight-medium);--rt-dynamic-selector-list-add-indent: 0;--rt-dynamic-selector-list-reset-color: var(--rt-color-text-primary);--rt-dynamic-selector-list-actions-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-divider-width-default: 0;--rt-dynamic-selector-list-controls-divider-color-default: var(--rt-color-border-default);--rt-dynamic-selector-list-row-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-offset-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-padding-end-default: 0;--rt-dynamic-selector-list-handle-padding-start-default: 0;--rt-dynamic-selector-list-handle-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-title-gap-default: var(--rt-space-sm);display:flex;flex-direction:column;gap:var(--rt-dynamic-selector-list-actions-offset, var(--rt-dynamic-selector-list-actions-offset-default))}.rt-dynamic-selector-list__rows{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector-list__row{display:flex;min-height:var(--rt-control-height-lg);box-sizing:border-box;align-items:center;padding:var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-end, var(--rt-dynamic-selector-list-row-padding-end-default)) var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-x);border-radius:var(--rt-dynamic-selector-list-row-radius);background:var(--rt-dynamic-selector-list-row-bg);color:var(--rt-color-text-primary);gap:var(--rt-space-sm)}.rt-dynamic-selector-list__handle{border-right:var(--rt-dynamic-selector-list-divider-width) solid var(--rt-color-border-default);cursor:grab;margin-inline-end:calc(var(--rt-dynamic-selector-list-title-gap, var(--rt-dynamic-selector-list-title-gap-default)) - var(--rt-space-sm));padding-inline:var(--rt-dynamic-selector-list-handle-padding-start, var(--rt-dynamic-selector-list-handle-padding-start-default)) var(--rt-dynamic-selector-list-handle-padding-end, var(--rt-dynamic-selector-list-handle-padding-end-default))}.rt-dynamic-selector-list__title{min-width:0;flex:1 1 auto;font-size:var(--rt-text-md);overflow-wrap:anywhere}.rt-dynamic-selector-list__title--nowrap{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-list__field{min-width:0;flex:1 1 auto}.rt-dynamic-selector-list__controls{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-dynamic-selector-list-controls-gap, var(--rt-dynamic-selector-list-controls-gap-default))}.rt-dynamic-selector-list__controls>:not(:last-child){border-inline-end:var(--rt-dynamic-selector-list-controls-divider-width, var(--rt-dynamic-selector-list-controls-divider-width-default)) solid var(--rt-dynamic-selector-list-controls-divider-color, var(--rt-dynamic-selector-list-controls-divider-color-default))}.rt-dynamic-selector-list__actions{display:flex;align-items:center;gap:var(--rt-dynamic-selector-list-actions-gap, var(--rt-dynamic-selector-list-actions-gap-default));padding-inline-end:var(--rt-dynamic-selector-list-actions-padding-end, var(--rt-dynamic-selector-list-actions-padding-end-default))}.rt-dynamic-selector-list__add{display:flex;min-width:0;flex:1 1 auto;align-items:center;padding-inline-start:var(--rt-dynamic-selector-list-add-indent)}.rt-dynamic-selector-list__add .rt-button{color:var(--rt-dynamic-selector-list-add-color, var(--rt-btn-color));font-weight:var(--rt-dynamic-selector-list-add-font-weight)}.rt-dynamic-selector-list__reset.rt-icon-button{--rt-icon-button-color: var(--rt-dynamic-selector-list-reset-color)}.rt-dynamic-selector-list__clear{flex:none}.rt-dynamic-selector-list__row.cdk-drag-preview{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-actions-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-divider-width-default: 0;--rt-dynamic-selector-list-controls-divider-color-default: var(--rt-color-border-default);--rt-dynamic-selector-list-row-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-offset-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-padding-end-default: 0;--rt-dynamic-selector-list-handle-padding-start-default: 0;--rt-dynamic-selector-list-handle-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-title-gap-default: var(--rt-space-sm);box-shadow:var(--rt-dynamic-selector-list-drag-shadow)}.rt-dynamic-selector-list__row.cdk-drag-placeholder{opacity:0}.rt-dynamic-selector-list__row.cdk-drag-animating,.rt-dynamic-selector-list__rows.cdk-drop-list-dragging .rt-dynamic-selector-list__row:not(.cdk-drag-placeholder){transition:transform var(--rt-dynamic-selector-list-drag-duration) ease-out}}.rt-dynamic-selector-list__row.cdk-drag-preview{padding:var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-end, var(--rt-space-2xs)) var(--rt-space-2xs) var(--rt-space-sm);background-color:var(--rt-color-bg-surface);background-image:linear-gradient(var(--rt-dynamic-selector-list-row-bg),var(--rt-dynamic-selector-list-row-bg));color:var(--rt-color-text-primary)}\n"],
239
151
  dependencies: [
240
152
  {
@@ -429,144 +341,10 @@ i0.ɵɵngDeclareClassMetadata({
429
341
  RtTooltipDirective
430
342
  ],
431
343
  host: { class: BEM_BLOCK$3 },
432
- template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span\n rtElem=\"title\"\n rtTooltipWhenTruncated\n [rtMod]=\"{ nowrap: !titleWrap() }\"\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n {{ row.label }}\n </span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n rtElem=\"reset\"\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"resetClicked.emit()\" />\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"dynamic-selector-clear\"\n size=\"sm\"\n [icon]=\"clearIcon()\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"cleared.emit()\" />\n }\n </div>\n }\n</ng-container>\n",
344
+ template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span\n rtElem=\"title\"\n rtTooltipWhenTruncated\n [rtMod]=\"{ nowrap: !titleWrap() }\"\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n {{ row.label }}\n </span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n rtElem=\"reset\"\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"onReset()\" />\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"dynamic-selector-clear\"\n size=\"sm\"\n [icon]=\"clearIcon()\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"onClear()\" />\n }\n </div>\n }\n</ng-container>\n",
433
345
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-list{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-drag-duration: var(--rt-duration-base);--rt-dynamic-selector-list-row-padding-x: var(--rt-space-sm);--rt-dynamic-selector-list-add-font-weight: var(--rt-font-weight-medium);--rt-dynamic-selector-list-add-indent: 0;--rt-dynamic-selector-list-reset-color: var(--rt-color-text-primary);--rt-dynamic-selector-list-actions-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-divider-width-default: 0;--rt-dynamic-selector-list-controls-divider-color-default: var(--rt-color-border-default);--rt-dynamic-selector-list-row-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-offset-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-padding-end-default: 0;--rt-dynamic-selector-list-handle-padding-start-default: 0;--rt-dynamic-selector-list-handle-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-title-gap-default: var(--rt-space-sm);display:flex;flex-direction:column;gap:var(--rt-dynamic-selector-list-actions-offset, var(--rt-dynamic-selector-list-actions-offset-default))}.rt-dynamic-selector-list__rows{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector-list__row{display:flex;min-height:var(--rt-control-height-lg);box-sizing:border-box;align-items:center;padding:var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-end, var(--rt-dynamic-selector-list-row-padding-end-default)) var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-x);border-radius:var(--rt-dynamic-selector-list-row-radius);background:var(--rt-dynamic-selector-list-row-bg);color:var(--rt-color-text-primary);gap:var(--rt-space-sm)}.rt-dynamic-selector-list__handle{border-right:var(--rt-dynamic-selector-list-divider-width) solid var(--rt-color-border-default);cursor:grab;margin-inline-end:calc(var(--rt-dynamic-selector-list-title-gap, var(--rt-dynamic-selector-list-title-gap-default)) - var(--rt-space-sm));padding-inline:var(--rt-dynamic-selector-list-handle-padding-start, var(--rt-dynamic-selector-list-handle-padding-start-default)) var(--rt-dynamic-selector-list-handle-padding-end, var(--rt-dynamic-selector-list-handle-padding-end-default))}.rt-dynamic-selector-list__title{min-width:0;flex:1 1 auto;font-size:var(--rt-text-md);overflow-wrap:anywhere}.rt-dynamic-selector-list__title--nowrap{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-list__field{min-width:0;flex:1 1 auto}.rt-dynamic-selector-list__controls{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-dynamic-selector-list-controls-gap, var(--rt-dynamic-selector-list-controls-gap-default))}.rt-dynamic-selector-list__controls>:not(:last-child){border-inline-end:var(--rt-dynamic-selector-list-controls-divider-width, var(--rt-dynamic-selector-list-controls-divider-width-default)) solid var(--rt-dynamic-selector-list-controls-divider-color, var(--rt-dynamic-selector-list-controls-divider-color-default))}.rt-dynamic-selector-list__actions{display:flex;align-items:center;gap:var(--rt-dynamic-selector-list-actions-gap, var(--rt-dynamic-selector-list-actions-gap-default));padding-inline-end:var(--rt-dynamic-selector-list-actions-padding-end, var(--rt-dynamic-selector-list-actions-padding-end-default))}.rt-dynamic-selector-list__add{display:flex;min-width:0;flex:1 1 auto;align-items:center;padding-inline-start:var(--rt-dynamic-selector-list-add-indent)}.rt-dynamic-selector-list__add .rt-button{color:var(--rt-dynamic-selector-list-add-color, var(--rt-btn-color));font-weight:var(--rt-dynamic-selector-list-add-font-weight)}.rt-dynamic-selector-list__reset.rt-icon-button{--rt-icon-button-color: var(--rt-dynamic-selector-list-reset-color)}.rt-dynamic-selector-list__clear{flex:none}.rt-dynamic-selector-list__row.cdk-drag-preview{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-actions-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-gap-default: var(--rt-space-2xs);--rt-dynamic-selector-list-controls-divider-width-default: 0;--rt-dynamic-selector-list-controls-divider-color-default: var(--rt-color-border-default);--rt-dynamic-selector-list-row-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-offset-default: var(--rt-space-2xs);--rt-dynamic-selector-list-actions-padding-end-default: 0;--rt-dynamic-selector-list-handle-padding-start-default: 0;--rt-dynamic-selector-list-handle-padding-end-default: var(--rt-space-2xs);--rt-dynamic-selector-list-title-gap-default: var(--rt-space-sm);box-shadow:var(--rt-dynamic-selector-list-drag-shadow)}.rt-dynamic-selector-list__row.cdk-drag-placeholder{opacity:0}.rt-dynamic-selector-list__row.cdk-drag-animating,.rt-dynamic-selector-list__rows.cdk-drop-list-dragging .rt-dynamic-selector-list__row:not(.cdk-drag-placeholder){transition:transform var(--rt-dynamic-selector-list-drag-duration) ease-out}}.rt-dynamic-selector-list__row.cdk-drag-preview{padding:var(--rt-space-2xs) var(--rt-dynamic-selector-list-row-padding-end, var(--rt-space-2xs)) var(--rt-space-2xs) var(--rt-space-sm);background-color:var(--rt-color-bg-surface);background-image:linear-gradient(var(--rt-dynamic-selector-list-row-bg),var(--rt-dynamic-selector-list-row-bg));color:var(--rt-color-text-primary)}\n"]
434
346
  }]
435
- }],
436
- propDecorators: {
437
- rows: [{
438
- type: i0.Input,
439
- args: [{
440
- isSignal: true,
441
- alias: "rows",
442
- required: false
443
- }]
444
- }],
445
- draggable: [{
446
- type: i0.Input,
447
- args: [{
448
- isSignal: true,
449
- alias: "draggable",
450
- required: false
451
- }]
452
- }],
453
- editable: [{
454
- type: i0.Input,
455
- args: [{
456
- isSignal: true,
457
- alias: "editable",
458
- required: false
459
- }]
460
- }],
461
- disabled: [{
462
- type: i0.Input,
463
- args: [{
464
- isSignal: true,
465
- alias: "disabled",
466
- required: false
467
- }]
468
- }],
469
- actionsShown: [{
470
- type: i0.Input,
471
- args: [{
472
- isSignal: true,
473
- alias: "actionsShown",
474
- required: false
475
- }]
476
- }],
477
- resetClearShown: [{
478
- type: i0.Input,
479
- args: [{
480
- isSignal: true,
481
- alias: "resetClearShown",
482
- required: false
483
- }]
484
- }],
485
- removeShown: [{
486
- type: i0.Input,
487
- args: [{
488
- isSignal: true,
489
- alias: "removeShown",
490
- required: false
491
- }]
492
- }],
493
- resetDisabled: [{
494
- type: i0.Input,
495
- args: [{
496
- isSignal: true,
497
- alias: "resetDisabled",
498
- required: false
499
- }]
500
- }],
501
- clearDisabled: [{
502
- type: i0.Input,
503
- args: [{
504
- isSignal: true,
505
- alias: "clearDisabled",
506
- required: false
507
- }]
508
- }],
509
- buttonRadius: [{
510
- type: i0.Input,
511
- args: [{
512
- isSignal: true,
513
- alias: "buttonRadius",
514
- required: false
515
- }]
516
- }],
517
- clearIcon: [{
518
- type: i0.Input,
519
- args: [{
520
- isSignal: true,
521
- alias: "clearIcon",
522
- required: false
523
- }]
524
- }],
525
- titleWrap: [{
526
- type: i0.Input,
527
- args: [{
528
- isSignal: true,
529
- alias: "titleWrap",
530
- required: false
531
- }]
532
- }],
533
- titleTpl: [{
534
- type: i0.Input,
535
- args: [{
536
- isSignal: true,
537
- alias: "titleTpl",
538
- required: false
539
- }]
540
- }],
541
- controlsTpl: [{
542
- type: i0.Input,
543
- args: [{
544
- isSignal: true,
545
- alias: "controlsTpl",
546
- required: false
547
- }]
548
- }],
549
- removed: [{
550
- type: i0.Output,
551
- args: ["removed"]
552
- }],
553
- moved: [{
554
- type: i0.Output,
555
- args: ["moved"]
556
- }],
557
- edited: [{
558
- type: i0.Output,
559
- args: ["edited"]
560
- }],
561
- resetClicked: [{
562
- type: i0.Output,
563
- args: ["resetClicked"]
564
- }],
565
- cleared: [{
566
- type: i0.Output,
567
- args: ["cleared"]
568
- }]
569
- }
347
+ }]
570
348
  });
571
349
  var RtDynamicSelectorRowControlsDirective = class RtDynamicSelectorRowControlsDirective {
572
350
  constructor() {
@@ -642,42 +420,11 @@ function dynamicSelectorLabel(item, labelOf) {
642
420
  const label = labelOf(item);
643
421
  return typeof label === "string" || typeof label === "number" ? String(label) : null;
644
422
  }
645
- function dynamicSelectorMatches(label, query) {
646
- const words = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
647
- const text = label.toLowerCase();
648
- return words.every((word) => text.includes(word));
649
- }
650
- function dynamicMatchParts(label, query) {
651
- const words = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
652
- const text = label.toLowerCase();
653
- if (words.length === 0 || label === "" || text.length !== label.length) return [{
654
- text: label,
655
- matched: false
656
- }];
657
- const marks = Array.from({ length: label.length }, () => false);
658
- for (const word of words) {
659
- let from = text.indexOf(word);
660
- while (from !== -1) {
661
- marks.fill(true, from, from + word.length);
662
- from = text.indexOf(word, from + 1);
663
- }
664
- }
665
- const parts = [];
666
- let start = 0;
667
- for (let index = 1; index <= label.length; index++) if (index === label.length || marks[index] !== marks[start]) {
668
- parts.push({
669
- text: label.slice(start, index),
670
- matched: marks[start]
671
- });
672
- start = index;
673
- }
674
- return parts;
675
- }
676
423
  function selectableDynamicItems(items, chosenKeys, keyOf, labelOf, query, sortFn) {
677
424
  const chosen = new Set(chosenKeys);
678
425
  return items.filter((item) => {
679
426
  const label = dynamicSelectorLabel(item, labelOf);
680
- return label !== null && !chosen.has(keyOf(item)) && dynamicSelectorMatches(label, query);
427
+ return label !== null && !chosen.has(keyOf(item)) && rtSearchMatches(label, query);
681
428
  }).sort(sortFn ?? ((a, b) => (dynamicSelectorLabel(a, labelOf) ?? "").localeCompare(dynamicSelectorLabel(b, labelOf) ?? "")));
682
429
  }
683
430
  function toggleDynamicKey(keys, key, checked) {
@@ -744,9 +491,17 @@ function dynamicLabelCase(label, labelCase) {
744
491
  }
745
492
  const BEM_BLOCK$2 = "rt-dynamic-input";
746
493
  var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormControlBase {
494
+ #injector;
495
+ #parts;
496
+ #initial;
497
+ #invitationButtonIconDefault;
498
+ #invitationButtonAppearanceDefault;
499
+ #clearIconDefault;
500
+ #titleWrapDefault;
747
501
  constructor() {
748
- super(...arguments);
502
+ super();
749
503
  this.#injector = inject(Injector);
504
+ this.#parts = inject(RtDynamicSelectorPartsService);
750
505
  this.#initial = signal([], ...ngDevMode ? [{ debugName: "#initial" }] : /* istanbul ignore next */ []);
751
506
  this.#invitationButtonIconDefault = rtKitDefault("dynamicSelector", (it) => it.invitationButtonIcon, null);
752
507
  this.#invitationButtonAppearanceDefault = rtKitDefault("dynamicSelector", (it) => it.invitationButtonAppearance, "outlined");
@@ -823,14 +578,29 @@ var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormContro
823
578
  });
824
579
  this.listReset = output();
825
580
  this.listCleared = output();
826
- this.displayText = computed(() => this.value().join(", "), ...ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []);
827
- }
828
- #injector;
829
- #initial;
830
- #invitationButtonIconDefault;
831
- #invitationButtonAppearanceDefault;
832
- #clearIconDefault;
833
- #titleWrapDefault;
581
+ this.displayText = computed(() => this.value().join(", "), ...ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []);
582
+ this.#parts.bindList({
583
+ rows: this.rows,
584
+ draggable: this.draggable,
585
+ editable: this.editable,
586
+ disabled: this.isDisabled,
587
+ actionsShown: computed(() => !this.isInvitationShown()),
588
+ resetClearShown: this.listActionsShown,
589
+ removeShown: this.removeShown,
590
+ resetDisabled: this.isResetDisabled,
591
+ clearDisabled: this.isClearDisabled,
592
+ buttonRadius: this.buttonRadius,
593
+ clearIcon: this.clearIcon,
594
+ titleWrap: this.titleWrap,
595
+ titleTpl: signal(null),
596
+ controlsTpl: this.controlsTpl,
597
+ remove: (key) => this.onRemoved(key),
598
+ move: (move) => this.onMoved(move),
599
+ edit: (edit) => this.onEdited(edit),
600
+ reset: () => this.onReset(),
601
+ clear: () => this.onCleared()
602
+ });
603
+ }
834
604
  writeValue(value) {
835
605
  super.writeValue(value === null ? null : [...value]);
836
606
  this.#initial.set([...this.value()]);
@@ -885,7 +655,7 @@ var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormContro
885
655
  version: "22.2.2",
886
656
  ngImport: i0,
887
657
  type: RtDynamicInputComponent,
888
- deps: null,
658
+ deps: [],
889
659
  target: i0.ɵɵFactoryTarget.Component
890
660
  });
891
661
  }
@@ -1039,7 +809,7 @@ var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormContro
1039
809
  providers: [{
1040
810
  provide: RtFormControlBase,
1041
811
  useExisting: forwardRef(() => RtDynamicInputComponent)
1042
- }],
812
+ }, RtDynamicSelectorPartsService],
1043
813
  queries: [{
1044
814
  propertyName: "rowControls",
1045
815
  first: true,
@@ -1057,7 +827,7 @@ var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormContro
1057
827
  }],
1058
828
  usesInheritance: true,
1059
829
  ngImport: i0,
1060
- template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !isInvitationShown()) {\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [clearIcon]=\"clearIcon()\"\n [titleWrap]=\"titleWrap()\"\n [editable]=\"editable()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!isInvitationShown()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (edited)=\"onEdited($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (isFieldShown()) {\n <!-- Подпись поля рисует rt-field: у rt-input своей нет. Обёртка стоит только при подписи —\n пустая добавила бы зазор под полем и сдвинула прежний вид. -->\n @if (fieldLabel(); as label) {\n <rt-field qa-dataid=\"dynamic-input-field-label\" [label]=\"label\">\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n </rt-field>\n } @else {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n",
830
+ template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !isInvitationShown()) {\n <rt-dynamic-selector-list>\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (isFieldShown()) {\n <!-- Подпись поля рисует rt-field: у rt-input своей нет. Обёртка стоит только при подписи —\n пустая добавила бы зазор под полем и сдвинула прежний вид. -->\n @if (fieldLabel(); as label) {\n <rt-field qa-dataid=\"dynamic-input-field-label\" [label]=\"label\">\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n </rt-field>\n } @else {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n",
1061
831
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-input{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-input__field,.rt-dynamic-input__invitation{min-width:0}}\n"],
1062
832
  dependencies: [
1063
833
  {
@@ -1114,30 +884,7 @@ var RtDynamicInputComponent = class RtDynamicInputComponent extends RtFormContro
1114
884
  {
1115
885
  kind: "component",
1116
886
  type: RtDynamicSelectorListComponent,
1117
- selector: "rt-dynamic-selector-list",
1118
- inputs: [
1119
- "rows",
1120
- "draggable",
1121
- "editable",
1122
- "disabled",
1123
- "actionsShown",
1124
- "resetClearShown",
1125
- "removeShown",
1126
- "resetDisabled",
1127
- "clearDisabled",
1128
- "buttonRadius",
1129
- "clearIcon",
1130
- "titleWrap",
1131
- "titleTpl",
1132
- "controlsTpl"
1133
- ],
1134
- outputs: [
1135
- "removed",
1136
- "moved",
1137
- "edited",
1138
- "resetClicked",
1139
- "cleared"
1140
- ]
887
+ selector: "rt-dynamic-selector-list"
1141
888
  },
1142
889
  {
1143
890
  kind: "component",
@@ -1211,12 +958,13 @@ i0.ɵɵngDeclareClassMetadata({
1211
958
  providers: [{
1212
959
  provide: RtFormControlBase,
1213
960
  useExisting: forwardRef(() => RtDynamicInputComponent)
1214
- }],
961
+ }, RtDynamicSelectorPartsService],
1215
962
  host: { class: BEM_BLOCK$2 },
1216
- template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !isInvitationShown()) {\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [clearIcon]=\"clearIcon()\"\n [titleWrap]=\"titleWrap()\"\n [editable]=\"editable()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!isInvitationShown()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (edited)=\"onEdited($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (isFieldShown()) {\n <!-- Подпись поля рисует rt-field: у rt-input своей нет. Обёртка стоит только при подписи —\n пустая добавила бы зазор под полем и сдвинула прежний вид. -->\n @if (fieldLabel(); as label) {\n <rt-field qa-dataid=\"dynamic-input-field-label\" [label]=\"label\">\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n </rt-field>\n } @else {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n",
963
+ template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !isInvitationShown()) {\n <rt-dynamic-selector-list>\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (isFieldShown()) {\n <!-- Подпись поля рисует rt-field: у rt-input своей нет. Обёртка стоит только при подписи —\n пустая добавила бы зазор под полем и сдвинула прежний вид. -->\n @if (fieldLabel(); as label) {\n <rt-field qa-dataid=\"dynamic-input-field-label\" [label]=\"label\">\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n </rt-field>\n } @else {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [appearance]=\"fieldAppearance()\"\n [controlId]=\"effectiveControlId()\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n",
1217
964
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-input{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-input__field,.rt-dynamic-input__invitation{min-width:0}}\n"]
1218
965
  }]
1219
966
  }],
967
+ ctorParameters: () => [],
1220
968
  propDecorators: {
1221
969
  field: [{
1222
970
  type: i0.ViewChild,
@@ -1392,12 +1140,23 @@ i0.ɵɵngDeclareClassMetadata({
1392
1140
  }
1393
1141
  });
1394
1142
  const BEM_BLOCK$1 = "rt-dynamic-selector-popup";
1143
+ const ROW_CONTROL = `.${BEM_BLOCK$1}__row [role="checkbox"], .${BEM_BLOCK$1}__row [role="radio"]`;
1395
1144
  const RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE = 500;
1396
1145
  var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1397
1146
  constructor() {
1398
1147
  this.#destroyRef = inject(DestroyRef);
1148
+ this.#host = inject(ElementRef);
1399
1149
  this.#injector = inject(Injector);
1400
1150
  this.#searchSource = new Subject();
1151
+ this.#source = inject(RtDynamicSelectorPartsService).popup;
1152
+ this.optionList = new RtOptionList({
1153
+ panelId: () => BEM_BLOCK$1,
1154
+ isOpen: () => false,
1155
+ count: () => this.rowItems().length,
1156
+ chooseKeys: /* @__PURE__ */ new Set(),
1157
+ sideKeys: false,
1158
+ edgeKeys: true
1159
+ });
1401
1160
  this.searchLabel = rtKitLabel("dynamicSelectorSearch");
1402
1161
  this.searchField = viewChild("searchField", {
1403
1162
  ...ngDevMode ? { debugName: "searchField" } : /* istanbul ignore next */ {},
@@ -1420,7 +1179,7 @@ var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1420
1179
  if (!this.localSearch() || query.trim() === "") return [...this.entities()];
1421
1180
  return this.entities().filter((item) => {
1422
1181
  const label = dynamicSelectorLabel(item, (entity) => this.#labelOf(entity));
1423
- return label !== null && dynamicSelectorMatches(label, query);
1182
+ return label !== null && rtSearchMatches(label, query);
1424
1183
  });
1425
1184
  }, ...ngDevMode ? [{ debugName: "found" }] : /* istanbul ignore next */ []);
1426
1185
  this.rows = computed(() => dynamicPopupRows(this.entities(), this.found(), this.raised(), (item) => this.#keyOf(item), this.query()), ...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
@@ -1436,7 +1195,7 @@ var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1436
1195
  entity: item,
1437
1196
  key: this.#keyOf(item),
1438
1197
  label: labelOf(item),
1439
- parts: highlight ? dynamicMatchParts(labelOf(item), query) : [{
1198
+ parts: highlight ? rtMatchParts(labelOf(item), query) : [{
1440
1199
  text: labelOf(item),
1441
1200
  matched: false
1442
1201
  }],
@@ -1454,76 +1213,46 @@ var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1454
1213
  this.lastPinnedKey = computed(() => lastPinnedDynamicKey(this.rows().found, this.pinnedKeys(), (item) => this.#keyOf(item)), ...ngDevMode ? [{ debugName: "lastPinnedKey" }] : /* istanbul ignore next */ []);
1455
1214
  this.isApplyDisabled = computed(() => this.ticked().length === 0 || this.loading(), ...ngDevMode ? [{ debugName: "isApplyDisabled" }] : /* istanbul ignore next */ []);
1456
1215
  this.isNavShown = computed(() => !!this.navigateTitle() && !!this.navigateLink(), ...ngDevMode ? [{ debugName: "isNavShown" }] : /* istanbul ignore next */ []);
1457
- this.entities = input([], ...ngDevMode ? [{ debugName: "entities" }] : /* istanbul ignore next */ []);
1458
- this.keyExp = input.required(...ngDevMode ? [{ debugName: "keyExp" }] : /* istanbul ignore next */ []);
1459
- this.displayExp = input.required(...ngDevMode ? [{ debugName: "displayExp" }] : /* istanbul ignore next */ []);
1460
- this.displayWith = input(null, ...ngDevMode ? [{ debugName: "displayWith" }] : /* istanbul ignore next */ []);
1461
- this.mode = input("multi", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
1462
- this.multiToggleShown = input(false, {
1463
- ...ngDevMode ? { debugName: "multiToggleShown" } : /* istanbul ignore next */ {},
1464
- transform: booleanAttribute
1465
- });
1466
- this.selectAllShown = input(true, {
1467
- ...ngDevMode ? { debugName: "selectAllShown" } : /* istanbul ignore next */ {},
1468
- transform: booleanAttribute
1469
- });
1470
- this.localSearch = input(true, {
1471
- ...ngDevMode ? { debugName: "localSearch" } : /* istanbul ignore next */ {},
1472
- transform: booleanAttribute
1473
- });
1474
- this.lazyLoad = input(false, {
1475
- ...ngDevMode ? { debugName: "lazyLoad" } : /* istanbul ignore next */ {},
1476
- transform: booleanAttribute
1477
- });
1478
- this.loading = input(false, {
1479
- ...ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {},
1480
- transform: booleanAttribute
1481
- });
1482
- this.fetching = input(false, {
1483
- ...ngDevMode ? { debugName: "fetching" } : /* istanbul ignore next */ {},
1484
- transform: booleanAttribute
1485
- });
1486
- this.pinnedKeys = input([], ...ngDevMode ? [{ debugName: "pinnedKeys" }] : /* istanbul ignore next */ []);
1487
- this.navigateTitle = input("", ...ngDevMode ? [{ debugName: "navigateTitle" }] : /* istanbul ignore next */ []);
1488
- this.navigateLink = input("", ...ngDevMode ? [{ debugName: "navigateLink" }] : /* istanbul ignore next */ []);
1489
- this.searchTerm = input("", ...ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []);
1490
- this.searchAppearance = input("outline", ...ngDevMode ? [{ debugName: "searchAppearance" }] : /* istanbul ignore next */ []);
1491
- this.searchRadius = input(null, ...ngDevMode ? [{ debugName: "searchRadius" }] : /* istanbul ignore next */ []);
1492
- this.emptyResultsText = input("", ...ngDevMode ? [{ debugName: "emptyResultsText" }] : /* istanbul ignore next */ []);
1493
- this.applyLabel = input("", ...ngDevMode ? [{ debugName: "applyLabel" }] : /* istanbul ignore next */ []);
1494
- this.applyLabelCase = input("none", ...ngDevMode ? [{ debugName: "applyLabelCase" }] : /* istanbul ignore next */ []);
1495
- this.autofocusSearch = input(false, {
1496
- ...ngDevMode ? { debugName: "autofocusSearch" } : /* istanbul ignore next */ {},
1497
- transform: booleanAttribute
1498
- });
1499
- this.titleWrap = input(true, {
1500
- ...ngDevMode ? { debugName: "titleWrap" } : /* istanbul ignore next */ {},
1501
- transform: booleanAttribute
1502
- });
1503
- this.highlightSearch = input(false, {
1504
- ...ngDevMode ? { debugName: "highlightSearch" } : /* istanbul ignore next */ {},
1505
- transform: booleanAttribute
1506
- });
1507
- this.applied = output();
1508
- this.cancelled = output();
1509
- this.searchChange = output();
1510
- this.loadMore = output();
1511
- this.temporaryChoiceChange = output();
1216
+ this.entities = this.#source.entities;
1217
+ this.keyExp = this.#source.settings.keyExp;
1218
+ this.displayExp = this.#source.settings.displayExp;
1219
+ this.displayWith = this.#source.settings.displayWith;
1220
+ this.mode = this.#source.settings.mode;
1221
+ this.multiToggleShown = this.#source.settings.multiToggleShown;
1222
+ this.selectAllShown = this.#source.settings.selectAllShown;
1223
+ this.localSearch = this.#source.settings.localSearch;
1224
+ this.lazyLoad = this.#source.settings.lazyLoad;
1225
+ this.loading = this.#source.settings.loading;
1226
+ this.fetching = this.#source.settings.fetching;
1227
+ this.pinnedKeys = this.#source.settings.pinnedKeys;
1228
+ this.navigateTitle = this.#source.settings.navigateTitle;
1229
+ this.navigateLink = this.#source.settings.navigateLink;
1230
+ this.searchTerm = this.#source.settings.searchTerm;
1231
+ this.searchAppearance = this.#source.settings.searchAppearance;
1232
+ this.searchRadius = this.#source.settings.searchRadius;
1233
+ this.emptyResultsText = this.#source.settings.emptyResultsText;
1234
+ this.applyLabel = this.#source.settings.applyLabel;
1235
+ this.applyLabelCase = this.#source.settings.applyLabelCase;
1236
+ this.autofocusSearch = this.#source.settings.autofocusSearch;
1237
+ this.titleWrap = this.#source.settings.titleWrap;
1238
+ this.highlightSearch = this.#source.settings.highlightSearch;
1512
1239
  }
1513
1240
  #destroyRef;
1241
+ #host;
1514
1242
  #injector;
1515
1243
  #searchSource;
1244
+ #source;
1516
1245
  ngOnInit() {
1517
1246
  this.query.set(this.searchTerm());
1518
- this.temporaryChoiceChange.emit([]);
1519
- this.#searchSource.pipe(debounceTime(500), takeUntilDestroyed(this.#destroyRef)).subscribe((query) => this.searchChange.emit(query));
1247
+ this.#source.temporaryChoice([]);
1248
+ this.#searchSource.pipe(debounceTime(500), takeUntilDestroyed(this.#destroyRef)).subscribe((query) => this.#source.search(query));
1520
1249
  if (this.autofocusSearch()) afterNextRender(() => this.searchField()?.nativeElement.querySelector("input")?.focus({ preventScroll: true }), { injector: this.#injector });
1521
1250
  }
1522
1251
  onQueryChange(value) {
1523
1252
  const query = value ?? "";
1524
1253
  this.raised.set([...this.ticked()]);
1525
1254
  this.query.set(query);
1526
- this.temporaryChoiceChange.emit(this.#tickedEntities());
1255
+ this.#source.temporaryChoice(this.#tickedEntities());
1527
1256
  if (!this.localSearch()) this.#searchSource.next(query);
1528
1257
  }
1529
1258
  onRowClick(event, item) {
@@ -1541,210 +1270,77 @@ var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1541
1270
  onMultiToggle(value) {
1542
1271
  this.isMultiOn.set(value);
1543
1272
  }
1544
- onApply() {
1545
- if (!this.isApplyDisabled()) this.applied.emit([...this.ticked()]);
1546
- }
1547
- onCancel() {
1548
- this.cancelled.emit();
1549
- }
1550
- #tickedEntities() {
1551
- return this.ticked().map((key) => this.entities().find((item) => this.#keyOf(item) === key)).filter((item) => item !== void 0);
1552
- }
1553
- #keyOf(item) {
1554
- return item[this.keyExp()];
1555
- }
1556
- #labelOf(item) {
1557
- const displayWith = this.displayWith();
1558
- return displayWith === null ? item[this.displayExp()] : displayWith(item);
1559
- }
1560
- static {
1561
- this.ɵfac = i0.ɵɵngDeclareFactory({
1562
- minVersion: "12.0.0",
1563
- version: "22.2.2",
1564
- ngImport: i0,
1565
- type: RtDynamicSelectorPopupComponent,
1566
- deps: [],
1567
- target: i0.ɵɵFactoryTarget.Component
1568
- });
1569
- }
1570
- static {
1571
- this.ɵcmp = i0.ɵɵngDeclareComponent({
1572
- minVersion: "17.0.0",
1573
- version: "22.2.2",
1574
- type: RtDynamicSelectorPopupComponent,
1575
- isStandalone: true,
1576
- selector: "rt-dynamic-selector-popup",
1577
- inputs: {
1578
- entities: {
1579
- classPropertyName: "entities",
1580
- publicName: "entities",
1581
- isSignal: true,
1582
- isRequired: false,
1583
- transformFunction: null
1584
- },
1585
- keyExp: {
1586
- classPropertyName: "keyExp",
1587
- publicName: "keyExp",
1588
- isSignal: true,
1589
- isRequired: true,
1590
- transformFunction: null
1591
- },
1592
- displayExp: {
1593
- classPropertyName: "displayExp",
1594
- publicName: "displayExp",
1595
- isSignal: true,
1596
- isRequired: true,
1597
- transformFunction: null
1598
- },
1599
- displayWith: {
1600
- classPropertyName: "displayWith",
1601
- publicName: "displayWith",
1602
- isSignal: true,
1603
- isRequired: false,
1604
- transformFunction: null
1605
- },
1606
- mode: {
1607
- classPropertyName: "mode",
1608
- publicName: "mode",
1609
- isSignal: true,
1610
- isRequired: false,
1611
- transformFunction: null
1612
- },
1613
- multiToggleShown: {
1614
- classPropertyName: "multiToggleShown",
1615
- publicName: "multiToggleShown",
1616
- isSignal: true,
1617
- isRequired: false,
1618
- transformFunction: null
1619
- },
1620
- selectAllShown: {
1621
- classPropertyName: "selectAllShown",
1622
- publicName: "selectAllShown",
1623
- isSignal: true,
1624
- isRequired: false,
1625
- transformFunction: null
1626
- },
1627
- localSearch: {
1628
- classPropertyName: "localSearch",
1629
- publicName: "localSearch",
1630
- isSignal: true,
1631
- isRequired: false,
1632
- transformFunction: null
1633
- },
1634
- lazyLoad: {
1635
- classPropertyName: "lazyLoad",
1636
- publicName: "lazyLoad",
1637
- isSignal: true,
1638
- isRequired: false,
1639
- transformFunction: null
1640
- },
1641
- loading: {
1642
- classPropertyName: "loading",
1643
- publicName: "loading",
1644
- isSignal: true,
1645
- isRequired: false,
1646
- transformFunction: null
1647
- },
1648
- fetching: {
1649
- classPropertyName: "fetching",
1650
- publicName: "fetching",
1651
- isSignal: true,
1652
- isRequired: false,
1653
- transformFunction: null
1654
- },
1655
- pinnedKeys: {
1656
- classPropertyName: "pinnedKeys",
1657
- publicName: "pinnedKeys",
1658
- isSignal: true,
1659
- isRequired: false,
1660
- transformFunction: null
1661
- },
1662
- navigateTitle: {
1663
- classPropertyName: "navigateTitle",
1664
- publicName: "navigateTitle",
1665
- isSignal: true,
1666
- isRequired: false,
1667
- transformFunction: null
1668
- },
1669
- navigateLink: {
1670
- classPropertyName: "navigateLink",
1671
- publicName: "navigateLink",
1672
- isSignal: true,
1673
- isRequired: false,
1674
- transformFunction: null
1675
- },
1676
- searchTerm: {
1677
- classPropertyName: "searchTerm",
1678
- publicName: "searchTerm",
1679
- isSignal: true,
1680
- isRequired: false,
1681
- transformFunction: null
1682
- },
1683
- searchAppearance: {
1684
- classPropertyName: "searchAppearance",
1685
- publicName: "searchAppearance",
1686
- isSignal: true,
1687
- isRequired: false,
1688
- transformFunction: null
1689
- },
1690
- searchRadius: {
1691
- classPropertyName: "searchRadius",
1692
- publicName: "searchRadius",
1693
- isSignal: true,
1694
- isRequired: false,
1695
- transformFunction: null
1696
- },
1697
- emptyResultsText: {
1698
- classPropertyName: "emptyResultsText",
1699
- publicName: "emptyResultsText",
1700
- isSignal: true,
1701
- isRequired: false,
1702
- transformFunction: null
1703
- },
1704
- applyLabel: {
1705
- classPropertyName: "applyLabel",
1706
- publicName: "applyLabel",
1707
- isSignal: true,
1708
- isRequired: false,
1709
- transformFunction: null
1710
- },
1711
- applyLabelCase: {
1712
- classPropertyName: "applyLabelCase",
1713
- publicName: "applyLabelCase",
1714
- isSignal: true,
1715
- isRequired: false,
1716
- transformFunction: null
1717
- },
1718
- autofocusSearch: {
1719
- classPropertyName: "autofocusSearch",
1720
- publicName: "autofocusSearch",
1721
- isSignal: true,
1722
- isRequired: false,
1723
- transformFunction: null
1724
- },
1725
- titleWrap: {
1726
- classPropertyName: "titleWrap",
1727
- publicName: "titleWrap",
1728
- isSignal: true,
1729
- isRequired: false,
1730
- transformFunction: null
1731
- },
1732
- highlightSearch: {
1733
- classPropertyName: "highlightSearch",
1734
- publicName: "highlightSearch",
1735
- isSignal: true,
1736
- isRequired: false,
1737
- transformFunction: null
1738
- }
1739
- },
1740
- outputs: {
1741
- applied: "applied",
1742
- cancelled: "cancelled",
1743
- searchChange: "searchChange",
1744
- loadMore: "loadMore",
1745
- temporaryChoiceChange: "temporaryChoiceChange"
1273
+ onApply() {
1274
+ if (!this.isApplyDisabled()) this.#source.apply([...this.ticked()]);
1275
+ }
1276
+ onCancel() {
1277
+ this.#source.cancel();
1278
+ }
1279
+ onLoadMore() {
1280
+ this.#source.loadMore();
1281
+ }
1282
+ onKeydown(event) {
1283
+ const target = event.target;
1284
+ if (!(target instanceof Node)) return;
1285
+ const controls = Array.from(this.#host.nativeElement.querySelectorAll(ROW_CONTROL));
1286
+ const index = controls.findIndex((control) => control.contains(target));
1287
+ const inSearch = this.searchField()?.nativeElement.contains(target) ?? false;
1288
+ if (controls.length === 0 || index < 0 && !inSearch) return;
1289
+ this.optionList.activeIndex.set(index);
1290
+ if (this.#moveBy(this.optionList.actionOf(event.key), inSearch)) {
1291
+ event.preventDefault();
1292
+ controls[this.optionList.activeIndex()]?.focus();
1293
+ }
1294
+ }
1295
+ #moveBy(action, inSearch) {
1296
+ switch (action) {
1297
+ case "next":
1298
+ this.optionList.move(1);
1299
+ return true;
1300
+ case "previous":
1301
+ if (inSearch) this.optionList.last();
1302
+ else this.optionList.move(-1);
1303
+ return true;
1304
+ case "first":
1305
+ case "last":
1306
+ if (inSearch) return false;
1307
+ if (action === "first") this.optionList.first();
1308
+ else this.optionList.last();
1309
+ return true;
1310
+ default: return false;
1311
+ }
1312
+ }
1313
+ #tickedEntities() {
1314
+ return this.ticked().map((key) => this.entities().find((item) => this.#keyOf(item) === key)).filter((item) => item !== void 0);
1315
+ }
1316
+ #keyOf(item) {
1317
+ return item[this.keyExp()];
1318
+ }
1319
+ #labelOf(item) {
1320
+ const displayWith = this.displayWith();
1321
+ return displayWith === null ? item[this.displayExp()] : displayWith(item);
1322
+ }
1323
+ static {
1324
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1325
+ minVersion: "12.0.0",
1326
+ version: "22.2.2",
1327
+ ngImport: i0,
1328
+ type: RtDynamicSelectorPopupComponent,
1329
+ deps: [],
1330
+ target: i0.ɵɵFactoryTarget.Component
1331
+ });
1332
+ }
1333
+ static {
1334
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
1335
+ minVersion: "17.0.0",
1336
+ version: "22.2.2",
1337
+ type: RtDynamicSelectorPopupComponent,
1338
+ isStandalone: true,
1339
+ selector: "rt-dynamic-selector-popup",
1340
+ host: {
1341
+ listeners: { "keydown": "onKeydown($event)" },
1342
+ classAttribute: "rt-dynamic-selector-popup"
1746
1343
  },
1747
- host: { classAttribute: "rt-dynamic-selector-popup" },
1748
1344
  viewQueries: [{
1749
1345
  propertyName: "searchField",
1750
1346
  first: true,
@@ -1754,7 +1350,7 @@ var RtDynamicSelectorPopupComponent = class RtDynamicSelectorPopupComponent {
1754
1350
  isSignal: true
1755
1351
  }],
1756
1352
  ngImport: i0,
1757
- template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n #searchField\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [appearance]=\"searchAppearance()\"\n [radius]=\"searchRadius()\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated, nowrap: !titleWrap(), own: isSingle() && ownLabel() }\">\n @if (isSingle()) {\n <!-- Без переноса и при подсветке поиска подпись рисует окно рядом с кнопкой: подсказка\n меряет обрезку своего узла, а подпись внутри кнопки окну недоступна. -->\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"ownLabel() ? '' : row.label\"\n [ariaLabel]=\"ownLabel() ? row.label : null\"\n [rtMod]=\"{ fixed: ownLabel() }\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n @if (ownLabel()) {\n <!-- Фокус и клавиатура остаются на кнопке: она названа этой же подписью, а подпись даёт нажать мышью, как label. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\"\n (click)=\"onRadioChange(row.entity)\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n }\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"loadMore.emit()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"emptyText()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyText()\"\n [attr.aria-label]=\"applyText()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n\n <!-- Куски подписи стоят без пробелов между собой: пробел в разметке разорвал бы слово на подсвеченной границе. -->\n <!-- prettier-ignore -->\n <ng-template #labelParts let-parts>@for (part of parts; track $index) {@if (part.matched) {<mark rtElem=\"match\">{{ part.text }}</mark>} @else {{{ part.text }}}}</ng-template>\n</ng-container>\n",
1353
+ template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n #searchField\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [appearance]=\"searchAppearance()\"\n [radius]=\"searchRadius()\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated, nowrap: !titleWrap(), own: isSingle() && ownLabel() }\">\n @if (isSingle()) {\n <!-- Без переноса и при подсветке поиска подпись рисует окно рядом с кнопкой: подсказка\n меряет обрезку своего узла, а подпись внутри кнопки окну недоступна. -->\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"ownLabel() ? '' : row.label\"\n [ariaLabel]=\"ownLabel() ? row.label : null\"\n [rtMod]=\"{ fixed: ownLabel() }\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n @if (ownLabel()) {\n <!-- Фокус и клавиатура остаются на кнопке: она названа этой же подписью, а подпись даёт нажать мышью, как label. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\"\n (click)=\"onRadioChange(row.entity)\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n }\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"onLoadMore()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"emptyText()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyText()\"\n [attr.aria-label]=\"applyText()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n\n <!-- Куски подписи стоят без пробелов между собой: пробел в разметке разорвал бы слово на подсвеченной границе. -->\n <!-- prettier-ignore -->\n <ng-template #labelParts let-parts>@for (part of parts; track $index) {@if (part.matched) {<mark rtElem=\"match\">{{ part.text }}</mark>} @else {{{ part.text }}}}</ng-template>\n</ng-container>\n",
1758
1354
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup{--rt-dynamic-selector-popup-width-default: calc(var(--rt-size-40) * 2);--rt-dynamic-selector-popup-max-height-default: calc(var(--rt-size-100) + var(--rt-size-20));--rt-dynamic-selector-popup-radius-default: var(--rt-radius-md);--rt-dynamic-selector-popup-border-width-default: var(--rt-border-width-thin);--rt-dynamic-selector-popup-shadow-default: var(--rt-shadow-lg);--rt-dynamic-selector-popup-bg-default: var(--rt-color-bg-surface);--rt-dynamic-selector-popup-min-height-default: 0;--rt-dynamic-selector-popup-padding-default: var(--rt-space-md);--rt-dynamic-selector-popup-foot-border-width-default: var( --rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default) );--rt-dynamic-selector-popup-nav-color-default: var(--rt-color-text-link);--rt-dynamic-selector-popup-button-height-default: var(--rt-control-height-md);--rt-dynamic-selector-popup-button-font-size-default: .95rem;--rt-dynamic-selector-popup-empty-icon-size-default: var(--rt-size-8);--rt-dynamic-selector-popup-empty-icon-wrap-bg-default: var(--rt-color-bg-subtle);--rt-dynamic-selector-popup-empty-text-size-default: var(--rt-text-md);--rt-dynamic-selector-popup-empty-text-weight-default: var(--rt-font-weight-medium);--rt-dynamic-selector-popup-empty-text-color-default: var(--rt-color-text-primary);--rt-dynamic-selector-popup-highlight-color-default: var(--rt-color-text-primary);--rt-dynamic-selector-popup-highlight-weight-default: var(--rt-font-weight-semibold);--rt-dynamic-selector-popup-highlight-bg-default: transparent;--rt-dynamic-selector-popup-highlight-radius-default: 0;--rt-dynamic-selector-popup-option-line-height-default: normal;--rt-dynamic-selector-popup-option-min-height-default: 0;--rt-dynamic-selector-popup-empty-gap-default: calc(var(--rt-space-xs) + var(--rt-space-sm));--rt-dynamic-selector-popup-foot-padding-default: var(--rt-space-sm) var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default)) 0;display:flex;width:var(--rt-dynamic-selector-popup-width, var(--rt-dynamic-selector-popup-width-default));max-width:calc(100vw - var(--rt-space-md) * 2);min-height:var(--rt-dynamic-selector-popup-min-height, var(--rt-dynamic-selector-popup-min-height-default));max-height:var(--rt-dynamic-selector-popup-max-height, var(--rt-dynamic-selector-popup-max-height-default));box-sizing:border-box;flex-direction:column;border:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);border-radius:var(--rt-dynamic-selector-popup-radius, var(--rt-dynamic-selector-popup-radius-default));background:var(--rt-dynamic-selector-popup-bg, var(--rt-dynamic-selector-popup-bg-default));box-shadow:var(--rt-dynamic-selector-popup-shadow, var(--rt-dynamic-selector-popup-shadow-default));color:var(--rt-color-text-primary);gap:var(--rt-space-sm);padding-block:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__head{display:flex;flex-direction:column;gap:var(--rt-space-sm);padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__controls{display:flex;flex-direction:column;border-bottom:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__multi{display:flex;flex-wrap:wrap;align-items:center;gap:var(--rt-space-2xs) var(--rt-space-sm)}.rt-dynamic-selector-popup__multi-label{font-size:var(--rt-text-sm)}.rt-dynamic-selector-popup__multi-hint-icon{color:var(--rt-color-text-muted)}.rt-dynamic-selector-popup__multi-hint{display:none;flex-basis:100%;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}@media(width<=1080px){.rt-dynamic-selector-popup__multi-hint{display:block}.rt-dynamic-selector-popup__multi .rt-dynamic-selector-popup__multi-hint-icon{display:none}}.rt-dynamic-selector-popup__select-all{min-width:0}.rt-dynamic-selector-popup__state{display:flex;flex:1 1 auto;align-items:center;justify-content:center;padding:var(--rt-space-md)}.rt-dynamic-selector-popup__list{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow-y:auto;padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__sentinel{min-height:var(--rt-size-1)}.rt-dynamic-selector-popup__fetching{display:flex;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__empty{flex:1 1 auto;padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__empty .rt-empty-state__icon-wrap{margin-bottom:calc(var(--rt-dynamic-selector-popup-empty-gap, var(--rt-dynamic-selector-popup-empty-gap-default)) - var(--rt-space-sm))}.rt-dynamic-selector-popup__empty.rt-empty-state{--rt-empty-state-icon-size: var( --rt-dynamic-selector-popup-empty-icon-size, var(--rt-dynamic-selector-popup-empty-icon-size-default) );--rt-empty-state-icon-wrap-bg: var( --rt-dynamic-selector-popup-empty-icon-wrap-bg, var(--rt-dynamic-selector-popup-empty-icon-wrap-bg-default) );--rt-empty-state-title-size: var( --rt-dynamic-selector-popup-empty-text-size, var(--rt-dynamic-selector-popup-empty-text-size-default) );--rt-empty-state-title-weight: var( --rt-dynamic-selector-popup-empty-text-weight, var(--rt-dynamic-selector-popup-empty-text-weight-default) );--rt-empty-state-title-color: var( --rt-dynamic-selector-popup-empty-text-color, var(--rt-dynamic-selector-popup-empty-text-color-default) )}.rt-dynamic-selector-popup__foot{display:flex;align-items:center;justify-content:flex-end;padding:var(--rt-dynamic-selector-popup-foot-padding, var(--rt-dynamic-selector-popup-foot-padding-default));border-top:var(--rt-dynamic-selector-popup-foot-border-width, var(--rt-dynamic-selector-popup-foot-border-width-default)) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__foot--nav{justify-content:space-between}.rt-dynamic-selector-popup__nav{overflow:hidden;min-width:0;color:var(--rt-dynamic-selector-popup-nav-color, var(--rt-dynamic-selector-popup-nav-color-default));font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-popup__nav:hover{color:var(--rt-color-text-link-hover)}.rt-dynamic-selector-popup__actions{display:flex;flex:0 0 auto;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__actions .rt-button{--rt-btn-height: var(--rt-dynamic-selector-popup-button-height, var(--rt-dynamic-selector-popup-button-height-default));--rt-btn-font-size: var( --rt-dynamic-selector-popup-button-font-size, var(--rt-dynamic-selector-popup-button-font-size-default) )}}\n", "@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup__row{display:flex;min-height:var(--rt-dynamic-selector-popup-option-min-height, var(--rt-dynamic-selector-popup-option-min-height-default));box-sizing:border-box;flex-direction:column;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--separated{border-bottom:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);margin-block-end:var(--rt-space-2xs);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__option{display:block;overflow-wrap:anywhere}.rt-dynamic-selector-popup__option-label{overflow-wrap:anywhere}.rt-dynamic-selector-popup__option-label,.rt-dynamic-selector-popup__option .rt-checkbox__label,.rt-dynamic-selector-popup__option .rt-radio-button__label{line-height:var(--rt-dynamic-selector-popup-option-line-height, var(--rt-dynamic-selector-popup-option-line-height-default))}.rt-dynamic-selector-popup__row--nowrap{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option{min-width:0;max-width:100%}.rt-dynamic-selector-popup__row--own{display:flex;flex-direction:row;align-items:flex-start;justify-content:flex-start;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__option--fixed{flex:0 0 auto}.rt-dynamic-selector-popup__row--own .rt-dynamic-selector-popup__option-label{min-width:0;flex:1 1 auto;color:var(--rt-color-text-primary);cursor:pointer;font-size:var(--rt-text-sm);-webkit-user-select:none;user-select:none}.rt-dynamic-selector-popup__match{border-radius:var(--rt-dynamic-selector-popup-highlight-radius, var(--rt-dynamic-selector-popup-highlight-radius-default));background:var(--rt-dynamic-selector-popup-highlight-bg, var(--rt-dynamic-selector-popup-highlight-bg-default));color:var(--rt-dynamic-selector-popup-highlight-color, var(--rt-dynamic-selector-popup-highlight-color-default));font-weight:var(--rt-dynamic-selector-popup-highlight-weight, var(--rt-dynamic-selector-popup-highlight-weight-default))}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option .rt-checkbox{max-width:100%}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option .rt-checkbox__label{overflow:hidden;min-width:0}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option-label{display:block;overflow:hidden;min-width:0;flex:1 1 auto;font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}}\n"],
1759
1355
  dependencies: [
1760
1356
  {
@@ -1990,228 +1586,26 @@ i0.ɵɵngDeclareClassMetadata({
1990
1586
  RtToggleSwitchComponent,
1991
1587
  RtTooltipDirective
1992
1588
  ],
1993
- host: { class: BEM_BLOCK$1 },
1994
- template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n #searchField\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [appearance]=\"searchAppearance()\"\n [radius]=\"searchRadius()\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated, nowrap: !titleWrap(), own: isSingle() && ownLabel() }\">\n @if (isSingle()) {\n <!-- Без переноса и при подсветке поиска подпись рисует окно рядом с кнопкой: подсказка\n меряет обрезку своего узла, а подпись внутри кнопки окну недоступна. -->\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"ownLabel() ? '' : row.label\"\n [ariaLabel]=\"ownLabel() ? row.label : null\"\n [rtMod]=\"{ fixed: ownLabel() }\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n @if (ownLabel()) {\n <!-- Фокус и клавиатура остаются на кнопке: она названа этой же подписью, а подпись даёт нажать мышью, как label. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\"\n (click)=\"onRadioChange(row.entity)\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n }\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"loadMore.emit()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"emptyText()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyText()\"\n [attr.aria-label]=\"applyText()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n\n <!-- Куски подписи стоят без пробелов между собой: пробел в разметке разорвал бы слово на подсвеченной границе. -->\n <!-- prettier-ignore -->\n <ng-template #labelParts let-parts>@for (part of parts; track $index) {@if (part.matched) {<mark rtElem=\"match\">{{ part.text }}</mark>} @else {{{ part.text }}}}</ng-template>\n</ng-container>\n",
1589
+ host: {
1590
+ class: BEM_BLOCK$1,
1591
+ "(keydown)": "onKeydown($event)"
1592
+ },
1593
+ template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n #searchField\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [appearance]=\"searchAppearance()\"\n [radius]=\"searchRadius()\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated, nowrap: !titleWrap(), own: isSingle() && ownLabel() }\">\n @if (isSingle()) {\n <!-- Без переноса и при подсветке поиска подпись рисует окно рядом с кнопкой: подсказка\n меряет обрезку своего узла, а подпись внутри кнопки окну недоступна. -->\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"ownLabel() ? '' : row.label\"\n [ariaLabel]=\"ownLabel() ? row.label : null\"\n [rtMod]=\"{ fixed: ownLabel() }\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n @if (ownLabel()) {\n <!-- Фокус и клавиатура остаются на кнопке: она названа этой же подписью, а подпись даёт нажать мышью, как label. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\"\n (click)=\"onRadioChange(row.entity)\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n }\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n <span\n rtElem=\"option-label\"\n qa-dataid=\"dynamic-selector-option-label\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"titleWrap() ? '' : row.label\">\n <ng-container *ngTemplateOutlet=\"labelParts; context: { $implicit: row.parts }\" />\n </span>\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"onLoadMore()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"emptyText()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyText()\"\n [attr.aria-label]=\"applyText()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n\n <!-- Куски подписи стоят без пробелов между собой: пробел в разметке разорвал бы слово на подсвеченной границе. -->\n <!-- prettier-ignore -->\n <ng-template #labelParts let-parts>@for (part of parts; track $index) {@if (part.matched) {<mark rtElem=\"match\">{{ part.text }}</mark>} @else {{{ part.text }}}}</ng-template>\n</ng-container>\n",
1995
1594
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup{--rt-dynamic-selector-popup-width-default: calc(var(--rt-size-40) * 2);--rt-dynamic-selector-popup-max-height-default: calc(var(--rt-size-100) + var(--rt-size-20));--rt-dynamic-selector-popup-radius-default: var(--rt-radius-md);--rt-dynamic-selector-popup-border-width-default: var(--rt-border-width-thin);--rt-dynamic-selector-popup-shadow-default: var(--rt-shadow-lg);--rt-dynamic-selector-popup-bg-default: var(--rt-color-bg-surface);--rt-dynamic-selector-popup-min-height-default: 0;--rt-dynamic-selector-popup-padding-default: var(--rt-space-md);--rt-dynamic-selector-popup-foot-border-width-default: var( --rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default) );--rt-dynamic-selector-popup-nav-color-default: var(--rt-color-text-link);--rt-dynamic-selector-popup-button-height-default: var(--rt-control-height-md);--rt-dynamic-selector-popup-button-font-size-default: .95rem;--rt-dynamic-selector-popup-empty-icon-size-default: var(--rt-size-8);--rt-dynamic-selector-popup-empty-icon-wrap-bg-default: var(--rt-color-bg-subtle);--rt-dynamic-selector-popup-empty-text-size-default: var(--rt-text-md);--rt-dynamic-selector-popup-empty-text-weight-default: var(--rt-font-weight-medium);--rt-dynamic-selector-popup-empty-text-color-default: var(--rt-color-text-primary);--rt-dynamic-selector-popup-highlight-color-default: var(--rt-color-text-primary);--rt-dynamic-selector-popup-highlight-weight-default: var(--rt-font-weight-semibold);--rt-dynamic-selector-popup-highlight-bg-default: transparent;--rt-dynamic-selector-popup-highlight-radius-default: 0;--rt-dynamic-selector-popup-option-line-height-default: normal;--rt-dynamic-selector-popup-option-min-height-default: 0;--rt-dynamic-selector-popup-empty-gap-default: calc(var(--rt-space-xs) + var(--rt-space-sm));--rt-dynamic-selector-popup-foot-padding-default: var(--rt-space-sm) var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default)) 0;display:flex;width:var(--rt-dynamic-selector-popup-width, var(--rt-dynamic-selector-popup-width-default));max-width:calc(100vw - var(--rt-space-md) * 2);min-height:var(--rt-dynamic-selector-popup-min-height, var(--rt-dynamic-selector-popup-min-height-default));max-height:var(--rt-dynamic-selector-popup-max-height, var(--rt-dynamic-selector-popup-max-height-default));box-sizing:border-box;flex-direction:column;border:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);border-radius:var(--rt-dynamic-selector-popup-radius, var(--rt-dynamic-selector-popup-radius-default));background:var(--rt-dynamic-selector-popup-bg, var(--rt-dynamic-selector-popup-bg-default));box-shadow:var(--rt-dynamic-selector-popup-shadow, var(--rt-dynamic-selector-popup-shadow-default));color:var(--rt-color-text-primary);gap:var(--rt-space-sm);padding-block:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__head{display:flex;flex-direction:column;gap:var(--rt-space-sm);padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__controls{display:flex;flex-direction:column;border-bottom:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__multi{display:flex;flex-wrap:wrap;align-items:center;gap:var(--rt-space-2xs) var(--rt-space-sm)}.rt-dynamic-selector-popup__multi-label{font-size:var(--rt-text-sm)}.rt-dynamic-selector-popup__multi-hint-icon{color:var(--rt-color-text-muted)}.rt-dynamic-selector-popup__multi-hint{display:none;flex-basis:100%;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}@media(width<=1080px){.rt-dynamic-selector-popup__multi-hint{display:block}.rt-dynamic-selector-popup__multi .rt-dynamic-selector-popup__multi-hint-icon{display:none}}.rt-dynamic-selector-popup__select-all{min-width:0}.rt-dynamic-selector-popup__state{display:flex;flex:1 1 auto;align-items:center;justify-content:center;padding:var(--rt-space-md)}.rt-dynamic-selector-popup__list{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow-y:auto;padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__sentinel{min-height:var(--rt-size-1)}.rt-dynamic-selector-popup__fetching{display:flex;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__empty{flex:1 1 auto;padding-inline:var(--rt-dynamic-selector-popup-padding, var(--rt-dynamic-selector-popup-padding-default))}.rt-dynamic-selector-popup__empty .rt-empty-state__icon-wrap{margin-bottom:calc(var(--rt-dynamic-selector-popup-empty-gap, var(--rt-dynamic-selector-popup-empty-gap-default)) - var(--rt-space-sm))}.rt-dynamic-selector-popup__empty.rt-empty-state{--rt-empty-state-icon-size: var( --rt-dynamic-selector-popup-empty-icon-size, var(--rt-dynamic-selector-popup-empty-icon-size-default) );--rt-empty-state-icon-wrap-bg: var( --rt-dynamic-selector-popup-empty-icon-wrap-bg, var(--rt-dynamic-selector-popup-empty-icon-wrap-bg-default) );--rt-empty-state-title-size: var( --rt-dynamic-selector-popup-empty-text-size, var(--rt-dynamic-selector-popup-empty-text-size-default) );--rt-empty-state-title-weight: var( --rt-dynamic-selector-popup-empty-text-weight, var(--rt-dynamic-selector-popup-empty-text-weight-default) );--rt-empty-state-title-color: var( --rt-dynamic-selector-popup-empty-text-color, var(--rt-dynamic-selector-popup-empty-text-color-default) )}.rt-dynamic-selector-popup__foot{display:flex;align-items:center;justify-content:flex-end;padding:var(--rt-dynamic-selector-popup-foot-padding, var(--rt-dynamic-selector-popup-foot-padding-default));border-top:var(--rt-dynamic-selector-popup-foot-border-width, var(--rt-dynamic-selector-popup-foot-border-width-default)) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__foot--nav{justify-content:space-between}.rt-dynamic-selector-popup__nav{overflow:hidden;min-width:0;color:var(--rt-dynamic-selector-popup-nav-color, var(--rt-dynamic-selector-popup-nav-color-default));font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-popup__nav:hover{color:var(--rt-color-text-link-hover)}.rt-dynamic-selector-popup__actions{display:flex;flex:0 0 auto;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__actions .rt-button{--rt-btn-height: var(--rt-dynamic-selector-popup-button-height, var(--rt-dynamic-selector-popup-button-height-default));--rt-btn-font-size: var( --rt-dynamic-selector-popup-button-font-size, var(--rt-dynamic-selector-popup-button-font-size-default) )}}\n", "@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup__row{display:flex;min-height:var(--rt-dynamic-selector-popup-option-min-height, var(--rt-dynamic-selector-popup-option-min-height-default));box-sizing:border-box;flex-direction:column;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--separated{border-bottom:var(--rt-dynamic-selector-popup-border-width, var(--rt-dynamic-selector-popup-border-width-default)) solid var(--rt-color-border-subtle);margin-block-end:var(--rt-space-2xs);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__option{display:block;overflow-wrap:anywhere}.rt-dynamic-selector-popup__option-label{overflow-wrap:anywhere}.rt-dynamic-selector-popup__option-label,.rt-dynamic-selector-popup__option .rt-checkbox__label,.rt-dynamic-selector-popup__option .rt-radio-button__label{line-height:var(--rt-dynamic-selector-popup-option-line-height, var(--rt-dynamic-selector-popup-option-line-height-default))}.rt-dynamic-selector-popup__row--nowrap{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option{min-width:0;max-width:100%}.rt-dynamic-selector-popup__row--own{display:flex;flex-direction:row;align-items:flex-start;justify-content:flex-start;gap:var(--rt-space-sm)}.rt-dynamic-selector-popup__option--fixed{flex:0 0 auto}.rt-dynamic-selector-popup__row--own .rt-dynamic-selector-popup__option-label{min-width:0;flex:1 1 auto;color:var(--rt-color-text-primary);cursor:pointer;font-size:var(--rt-text-sm);-webkit-user-select:none;user-select:none}.rt-dynamic-selector-popup__match{border-radius:var(--rt-dynamic-selector-popup-highlight-radius, var(--rt-dynamic-selector-popup-highlight-radius-default));background:var(--rt-dynamic-selector-popup-highlight-bg, var(--rt-dynamic-selector-popup-highlight-bg-default));color:var(--rt-dynamic-selector-popup-highlight-color, var(--rt-dynamic-selector-popup-highlight-color-default));font-weight:var(--rt-dynamic-selector-popup-highlight-weight, var(--rt-dynamic-selector-popup-highlight-weight-default))}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option .rt-checkbox{max-width:100%}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option .rt-checkbox__label{overflow:hidden;min-width:0}.rt-dynamic-selector-popup__row--nowrap .rt-dynamic-selector-popup__option-label{display:block;overflow:hidden;min-width:0;flex:1 1 auto;font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}}\n"]
1996
1595
  }]
1997
1596
  }],
1998
- propDecorators: {
1999
- searchField: [{
2000
- type: i0.ViewChild,
2001
- args: ["searchField", {
2002
- read: ElementRef,
2003
- isSignal: true
2004
- }]
2005
- }],
2006
- entities: [{
2007
- type: i0.Input,
2008
- args: [{
2009
- isSignal: true,
2010
- alias: "entities",
2011
- required: false
2012
- }]
2013
- }],
2014
- keyExp: [{
2015
- type: i0.Input,
2016
- args: [{
2017
- isSignal: true,
2018
- alias: "keyExp",
2019
- required: true
2020
- }]
2021
- }],
2022
- displayExp: [{
2023
- type: i0.Input,
2024
- args: [{
2025
- isSignal: true,
2026
- alias: "displayExp",
2027
- required: true
2028
- }]
2029
- }],
2030
- displayWith: [{
2031
- type: i0.Input,
2032
- args: [{
2033
- isSignal: true,
2034
- alias: "displayWith",
2035
- required: false
2036
- }]
2037
- }],
2038
- mode: [{
2039
- type: i0.Input,
2040
- args: [{
2041
- isSignal: true,
2042
- alias: "mode",
2043
- required: false
2044
- }]
2045
- }],
2046
- multiToggleShown: [{
2047
- type: i0.Input,
2048
- args: [{
2049
- isSignal: true,
2050
- alias: "multiToggleShown",
2051
- required: false
2052
- }]
2053
- }],
2054
- selectAllShown: [{
2055
- type: i0.Input,
2056
- args: [{
2057
- isSignal: true,
2058
- alias: "selectAllShown",
2059
- required: false
2060
- }]
2061
- }],
2062
- localSearch: [{
2063
- type: i0.Input,
2064
- args: [{
2065
- isSignal: true,
2066
- alias: "localSearch",
2067
- required: false
2068
- }]
2069
- }],
2070
- lazyLoad: [{
2071
- type: i0.Input,
2072
- args: [{
2073
- isSignal: true,
2074
- alias: "lazyLoad",
2075
- required: false
2076
- }]
2077
- }],
2078
- loading: [{
2079
- type: i0.Input,
2080
- args: [{
2081
- isSignal: true,
2082
- alias: "loading",
2083
- required: false
2084
- }]
2085
- }],
2086
- fetching: [{
2087
- type: i0.Input,
2088
- args: [{
2089
- isSignal: true,
2090
- alias: "fetching",
2091
- required: false
2092
- }]
2093
- }],
2094
- pinnedKeys: [{
2095
- type: i0.Input,
2096
- args: [{
2097
- isSignal: true,
2098
- alias: "pinnedKeys",
2099
- required: false
2100
- }]
2101
- }],
2102
- navigateTitle: [{
2103
- type: i0.Input,
2104
- args: [{
2105
- isSignal: true,
2106
- alias: "navigateTitle",
2107
- required: false
2108
- }]
2109
- }],
2110
- navigateLink: [{
2111
- type: i0.Input,
2112
- args: [{
2113
- isSignal: true,
2114
- alias: "navigateLink",
2115
- required: false
2116
- }]
2117
- }],
2118
- searchTerm: [{
2119
- type: i0.Input,
2120
- args: [{
2121
- isSignal: true,
2122
- alias: "searchTerm",
2123
- required: false
2124
- }]
2125
- }],
2126
- searchAppearance: [{
2127
- type: i0.Input,
2128
- args: [{
2129
- isSignal: true,
2130
- alias: "searchAppearance",
2131
- required: false
2132
- }]
2133
- }],
2134
- searchRadius: [{
2135
- type: i0.Input,
2136
- args: [{
2137
- isSignal: true,
2138
- alias: "searchRadius",
2139
- required: false
2140
- }]
2141
- }],
2142
- emptyResultsText: [{
2143
- type: i0.Input,
2144
- args: [{
2145
- isSignal: true,
2146
- alias: "emptyResultsText",
2147
- required: false
2148
- }]
2149
- }],
2150
- applyLabel: [{
2151
- type: i0.Input,
2152
- args: [{
2153
- isSignal: true,
2154
- alias: "applyLabel",
2155
- required: false
2156
- }]
2157
- }],
2158
- applyLabelCase: [{
2159
- type: i0.Input,
2160
- args: [{
2161
- isSignal: true,
2162
- alias: "applyLabelCase",
2163
- required: false
2164
- }]
2165
- }],
2166
- autofocusSearch: [{
2167
- type: i0.Input,
2168
- args: [{
2169
- isSignal: true,
2170
- alias: "autofocusSearch",
2171
- required: false
2172
- }]
2173
- }],
2174
- titleWrap: [{
2175
- type: i0.Input,
2176
- args: [{
2177
- isSignal: true,
2178
- alias: "titleWrap",
2179
- required: false
2180
- }]
2181
- }],
2182
- highlightSearch: [{
2183
- type: i0.Input,
2184
- args: [{
2185
- isSignal: true,
2186
- alias: "highlightSearch",
2187
- required: false
2188
- }]
2189
- }],
2190
- applied: [{
2191
- type: i0.Output,
2192
- args: ["applied"]
2193
- }],
2194
- cancelled: [{
2195
- type: i0.Output,
2196
- args: ["cancelled"]
2197
- }],
2198
- searchChange: [{
2199
- type: i0.Output,
2200
- args: ["searchChange"]
2201
- }],
2202
- loadMore: [{
2203
- type: i0.Output,
2204
- args: ["loadMore"]
2205
- }],
2206
- temporaryChoiceChange: [{
2207
- type: i0.Output,
2208
- args: ["temporaryChoiceChange"]
1597
+ propDecorators: { searchField: [{
1598
+ type: i0.ViewChild,
1599
+ args: ["searchField", {
1600
+ read: ElementRef,
1601
+ isSignal: true
2209
1602
  }]
2210
- }
1603
+ }] }
2211
1604
  });
2212
1605
  const BEM_BLOCK = "rt-dynamic-selector";
2213
1606
  var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtFormControlBase {
2214
1607
  #initial;
1608
+ #parts;
2215
1609
  #invitationButtonIconDefault;
2216
1610
  #invitationButtonAppearanceDefault;
2217
1611
  #clearIconDefault;
@@ -2226,6 +1620,7 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2226
1620
  constructor() {
2227
1621
  super();
2228
1622
  this.#initial = signal([], ...ngDevMode ? [{ debugName: "#initial" }] : /* istanbul ignore next */ []);
1623
+ this.#parts = inject(RtDynamicSelectorPartsService);
2229
1624
  this.#invitationButtonIconDefault = rtKitDefault("dynamicSelector", (it) => it.invitationButtonIcon, null);
2230
1625
  this.#invitationButtonAppearanceDefault = rtKitDefault("dynamicSelector", (it) => it.invitationButtonAppearance, "outlined");
2231
1626
  this.#clearIconDefault = rtKitDefault("dynamicSelector", (it) => it.clearIcon, "close");
@@ -2359,6 +1754,7 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2359
1754
  this.popupOpen = computed(() => this.popovers().some((popover) => popover.isOpen()), ...ngDevMode ? [{ debugName: "popupOpen" }] : /* istanbul ignore next */ []);
2360
1755
  this.displayText = computed(() => this.rows().map((row) => row.label).join(", "), ...ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []);
2361
1756
  toObservable(this.chosenEntities).pipe(takeUntilDestroyed()).subscribe((list) => this.#takeChosen(list));
1757
+ this.#bindParts();
2362
1758
  }
2363
1759
  writeValue(value) {
2364
1760
  super.writeValue(value === null ? null : [...value]);
@@ -2397,6 +1793,38 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2397
1793
  this.markTouched();
2398
1794
  this.popupOpenChange.emit(false);
2399
1795
  }
1796
+ #bindParts() {
1797
+ this.#parts.bindPopup({
1798
+ settings: this,
1799
+ entities: this.offered,
1800
+ apply: (keys) => this.onApplied(keys),
1801
+ cancel: () => this.onCancelled(),
1802
+ search: (query) => this.searchChange.emit(query),
1803
+ loadMore: () => this.loadMore.emit(),
1804
+ temporaryChoice: (entities) => this.temporaryChoiceChange.emit(entities)
1805
+ });
1806
+ this.#parts.bindList({
1807
+ rows: this.rows,
1808
+ draggable: this.draggable,
1809
+ editable: signal(false),
1810
+ disabled: this.isDisabled,
1811
+ actionsShown: computed(() => !this.invitation()),
1812
+ resetClearShown: this.listActionsShown,
1813
+ removeShown: this.removeShown,
1814
+ resetDisabled: this.isResetDisabled,
1815
+ clearDisabled: this.isClearDisabled,
1816
+ buttonRadius: this.buttonRadius,
1817
+ clearIcon: this.clearIcon,
1818
+ titleWrap: this.titleWrap,
1819
+ titleTpl: this.titleTpl,
1820
+ controlsTpl: this.controlsTpl,
1821
+ remove: (key) => this.onRemoved(key),
1822
+ move: (move) => this.onMoved(move),
1823
+ edit: () => void 0,
1824
+ reset: () => this.onReset(),
1825
+ clear: () => this.onCleared()
1826
+ });
1827
+ }
2400
1828
  #closePopup() {
2401
1829
  for (const popover of this.popovers()) popover.close();
2402
1830
  }
@@ -2742,7 +2170,7 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2742
2170
  providers: [{
2743
2171
  provide: RtFormControlBase,
2744
2172
  useExisting: forwardRef(() => RtDynamicSelectorComponent)
2745
- }],
2173
+ }, RtDynamicSelectorPartsService],
2746
2174
  queries: [{
2747
2175
  propertyName: "rowTitle",
2748
2176
  first: true,
@@ -2764,7 +2192,7 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2764
2192
  }],
2765
2193
  usesInheritance: true,
2766
2194
  ngImport: i0,
2767
- template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !invitation()) {\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [clearIcon]=\"clearIcon()\"\n [titleWrap]=\"titleWrap()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!invitation()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [titleTpl]=\"titleTpl()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup\n [entities]=\"offered()\"\n [keyExp]=\"keyExp()\"\n [displayExp]=\"displayExp()\"\n [displayWith]=\"displayWith()\"\n [mode]=\"mode()\"\n [multiToggleShown]=\"multiToggleShown()\"\n [selectAllShown]=\"selectAllShown()\"\n [localSearch]=\"localSearch()\"\n [lazyLoad]=\"lazyLoad()\"\n [loading]=\"loading()\"\n [fetching]=\"fetching()\"\n [pinnedKeys]=\"pinnedKeys()\"\n [navigateTitle]=\"navigateTitle()\"\n [navigateLink]=\"navigateLink()\"\n [searchTerm]=\"searchTerm()\"\n [searchAppearance]=\"searchAppearance()\"\n [searchRadius]=\"searchRadius()\"\n [emptyResultsText]=\"emptyResultsText()\"\n [titleWrap]=\"titleWrap()\"\n [highlightSearch]=\"highlightSearch()\"\n [applyLabel]=\"applyLabel()\"\n [applyLabelCase]=\"applyLabelCase()\"\n [autofocusSearch]=\"autofocusSearch()\"\n (applied)=\"onApplied($event)\"\n (cancelled)=\"onCancelled()\"\n (searchChange)=\"searchChange.emit($event)\"\n (loadMore)=\"loadMore.emit()\"\n (temporaryChoiceChange)=\"temporaryChoiceChange.emit($event)\" />\n </ng-template>\n</ng-container>\n",
2195
+ template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !invitation()) {\n <rt-dynamic-selector-list>\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup />\n </ng-template>\n</ng-container>\n",
2768
2196
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector{display:block;width:100%}.rt-dynamic-selector__content{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector__invitation,.rt-dynamic-selector__nothing{min-width:0}}\n"],
2769
2197
  dependencies: [
2770
2198
  {
@@ -2799,67 +2227,12 @@ var RtDynamicSelectorComponent = class RtDynamicSelectorComponent extends RtForm
2799
2227
  {
2800
2228
  kind: "component",
2801
2229
  type: RtDynamicSelectorListComponent,
2802
- selector: "rt-dynamic-selector-list",
2803
- inputs: [
2804
- "rows",
2805
- "draggable",
2806
- "editable",
2807
- "disabled",
2808
- "actionsShown",
2809
- "resetClearShown",
2810
- "removeShown",
2811
- "resetDisabled",
2812
- "clearDisabled",
2813
- "buttonRadius",
2814
- "clearIcon",
2815
- "titleWrap",
2816
- "titleTpl",
2817
- "controlsTpl"
2818
- ],
2819
- outputs: [
2820
- "removed",
2821
- "moved",
2822
- "edited",
2823
- "resetClicked",
2824
- "cleared"
2825
- ]
2230
+ selector: "rt-dynamic-selector-list"
2826
2231
  },
2827
2232
  {
2828
2233
  kind: "component",
2829
2234
  type: RtDynamicSelectorPopupComponent,
2830
- selector: "rt-dynamic-selector-popup",
2831
- inputs: [
2832
- "entities",
2833
- "keyExp",
2834
- "displayExp",
2835
- "displayWith",
2836
- "mode",
2837
- "multiToggleShown",
2838
- "selectAllShown",
2839
- "localSearch",
2840
- "lazyLoad",
2841
- "loading",
2842
- "fetching",
2843
- "pinnedKeys",
2844
- "navigateTitle",
2845
- "navigateLink",
2846
- "searchTerm",
2847
- "searchAppearance",
2848
- "searchRadius",
2849
- "emptyResultsText",
2850
- "applyLabel",
2851
- "applyLabelCase",
2852
- "autofocusSearch",
2853
- "titleWrap",
2854
- "highlightSearch"
2855
- ],
2856
- outputs: [
2857
- "applied",
2858
- "cancelled",
2859
- "searchChange",
2860
- "loadMore",
2861
- "temporaryChoiceChange"
2862
- ]
2235
+ selector: "rt-dynamic-selector-popup"
2863
2236
  },
2864
2237
  {
2865
2238
  kind: "component",
@@ -2922,9 +2295,9 @@ i0.ɵɵngDeclareClassMetadata({
2922
2295
  providers: [{
2923
2296
  provide: RtFormControlBase,
2924
2297
  useExisting: forwardRef(() => RtDynamicSelectorComponent)
2925
- }],
2298
+ }, RtDynamicSelectorPartsService],
2926
2299
  host: { class: BEM_BLOCK },
2927
- template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !invitation()) {\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [clearIcon]=\"clearIcon()\"\n [titleWrap]=\"titleWrap()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!invitation()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [titleTpl]=\"titleTpl()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup\n [entities]=\"offered()\"\n [keyExp]=\"keyExp()\"\n [displayExp]=\"displayExp()\"\n [displayWith]=\"displayWith()\"\n [mode]=\"mode()\"\n [multiToggleShown]=\"multiToggleShown()\"\n [selectAllShown]=\"selectAllShown()\"\n [localSearch]=\"localSearch()\"\n [lazyLoad]=\"lazyLoad()\"\n [loading]=\"loading()\"\n [fetching]=\"fetching()\"\n [pinnedKeys]=\"pinnedKeys()\"\n [navigateTitle]=\"navigateTitle()\"\n [navigateLink]=\"navigateLink()\"\n [searchTerm]=\"searchTerm()\"\n [searchAppearance]=\"searchAppearance()\"\n [searchRadius]=\"searchRadius()\"\n [emptyResultsText]=\"emptyResultsText()\"\n [titleWrap]=\"titleWrap()\"\n [highlightSearch]=\"highlightSearch()\"\n [applyLabel]=\"applyLabel()\"\n [applyLabelCase]=\"applyLabelCase()\"\n [autofocusSearch]=\"autofocusSearch()\"\n (applied)=\"onApplied($event)\"\n (cancelled)=\"onCancelled()\"\n (searchChange)=\"searchChange.emit($event)\"\n (loadMore)=\"loadMore.emit()\"\n (temporaryChoiceChange)=\"temporaryChoiceChange.emit($event)\" />\n </ng-template>\n</ng-container>\n",
2300
+ template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <!-- Под приглашением пустой список не рисуется: узел нулевой высоты сдвигал бы приглашение зазором. -->\n @if (rows().length > 0 || !invitation()) {\n <rt-dynamic-selector-list>\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n }\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [glyph]=\"invitationGlyph()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [appearance]=\"invitationButtonAppearance()\"\n [icon]=\"invitationButtonIcon()\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup />\n </ng-template>\n</ng-container>\n",
2928
2301
  styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector{display:block;width:100%}.rt-dynamic-selector__content{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector__invitation,.rt-dynamic-selector__nothing{min-width:0}}\n"]
2929
2302
  }]
2930
2303
  }],