@rt-tools/ui-kit-v2 0.29.1 → 0.31.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 (64) 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-rich-editor.mjs +4 -4
  25. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  26. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +37 -181
  27. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-service-block.mjs +131 -0
  29. package/fesm2022/rt-tools-ui-kit-v2-service-block.mjs.map +1 -0
  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-tag.mjs +2 -3
  33. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  34. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +2 -2
  35. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -1
  36. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +8 -13
  37. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
  38. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +12 -7
  39. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
  40. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +2 -2
  41. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  42. package/fesm2022/rt-tools-ui-kit-v2.mjs +1 -0
  43. package/package.json +5 -1
  44. package/src/lib/components/dynamic-selector/stories/component/test-dynamic-selector-popup-frame.component.scss +6 -0
  45. package/src/lib/components/page-header/rt-page-header.component.scss +4 -2
  46. package/src/lib/components/service-block/CONTEXT.md +37 -0
  47. package/src/lib/components/service-block/rt-service-block.component.scss +61 -0
  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-service-block.d.ts +34 -0
  59. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +5 -20
  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/types/rt-tools-ui-kit-v2.d.ts +1 -0
  64. package/src/styles/_place.scss +0 -7
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ElementRef, InputSignal, InputSignalWithTransform, ModelSignal, OnInit, OutputEmitterRef, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import { RtFormControlBase } from "@rt-tools/ui-kit-v2/form-control";
4
- import { IButton, IRtIcon, IRtInput, TRtRadius } from "@rt-tools/ui-kit-v2/core";
4
+ import { IButton, IRtIcon, IRtInput, RtOptionList, TRtRadius } from "@rt-tools/ui-kit-v2/core";
5
5
  import { CdkDragDrop } from "@angular/cdk/drag-drop";
6
6
  import { RtPopoverDirective } from "@rt-tools/ui-kit-v2/popover";
7
7
  /**
@@ -158,6 +158,7 @@ export declare class RtDynamicInputComponent extends RtFormControlBase<string[]>
158
158
  readonly listReset: OutputEmitterRef<void>;
159
159
  readonly listCleared: OutputEmitterRef<void>;
160
160
  readonly displayText: Signal<string>;
161
+ constructor();
161
162
  /** Записанное формой становится и списком, и значением для сброса; пустой массив список опустошает. */
162
163
  writeValue(value: string[] | null): void;
163
164
  protected onAdd(): void;
@@ -292,116 +293,30 @@ export declare class RtDynamicSelectorListComponent<TItem> {
292
293
  /** Строка, открытая для правки, и текст в её поле. */
293
294
  protected readonly editedIndex: WritableSignal<number | null>;
294
295
  protected readonly draft: WritableSignal<string>;
295
- readonly rows: InputSignal<ReadonlyArray<IRtDynamicSelector.ListRow<TItem>>>;
296
- readonly draggable: InputSignalWithTransform<boolean, unknown>;
297
- readonly editable: InputSignalWithTransform<boolean, unknown>;
298
- readonly disabled: InputSignalWithTransform<boolean, unknown>;
299
- /** Полоса под строками; приглашение вызывающего встаёт на её место. */
300
- readonly actionsShown: InputSignalWithTransform<boolean, unknown>;
301
- /** Сброс и очистка в полосе; без них в полосе остаётся кнопка добавления. */
302
- readonly resetClearShown: InputSignalWithTransform<boolean, unknown>;
303
- /** Корзина строк; без неё строки двигаются и правятся, но не убираются. */
304
- readonly removeShown: InputSignalWithTransform<boolean, unknown>;
305
- readonly resetDisabled: InputSignalWithTransform<boolean, unknown>;
306
- readonly clearDisabled: InputSignalWithTransform<boolean, unknown>;
307
- /** Шаг скругления кнопок-иконок списка; по умолчанию они круглые. */
308
- readonly buttonRadius: InputSignal<TRtRadius | null>;
309
- /** Значок кнопки «Очистить список»; по умолчанию крестик. */
310
- readonly clearIcon: InputSignal<IRtIcon.Name>;
311
- /** Название строки переносится; `false` ведёт его одной строкой с многоточием и подсказкой при обрезке. */
312
- readonly titleWrap: InputSignalWithTransform<boolean, unknown>;
313
- readonly titleTpl: InputSignal<TemplateRef<IRtDynamicSelector.RowContext<TItem>> | null>;
314
- readonly controlsTpl: InputSignal<TemplateRef<IRtDynamicSelector.RowContext<TItem>> | null>;
315
- readonly removed: OutputEmitterRef<unknown>;
316
- readonly moved: OutputEmitterRef<IRtDynamicSelector.Move>;
317
- readonly edited: OutputEmitterRef<IRtDynamicSelector.TextEdit>;
318
- readonly resetClicked: OutputEmitterRef<void>;
319
- readonly cleared: OutputEmitterRef<void>;
296
+ protected readonly rows: Signal<ReadonlyArray<IRtDynamicSelector.ListRow<TItem>>>;
297
+ protected readonly draggable: Signal<boolean>;
298
+ protected readonly editable: Signal<boolean>;
299
+ protected readonly disabled: Signal<boolean>;
300
+ protected readonly actionsShown: Signal<boolean>;
301
+ protected readonly resetClearShown: Signal<boolean>;
302
+ protected readonly removeShown: Signal<boolean>;
303
+ protected readonly resetDisabled: Signal<boolean>;
304
+ protected readonly clearDisabled: Signal<boolean>;
305
+ protected readonly buttonRadius: Signal<TRtRadius | null>;
306
+ protected readonly clearIcon: Signal<IRtIcon.Name>;
307
+ protected readonly titleWrap: Signal<boolean>;
308
+ protected readonly titleTpl: Signal<TemplateRef<IRtDynamicSelector.RowContext<TItem>> | null>;
309
+ protected readonly controlsTpl: Signal<TemplateRef<IRtDynamicSelector.RowContext<TItem>> | null>;
320
310
  /** Строка, взятая из чужого списка, ничего не меняет; брошенная на своё место — тоже. */
321
311
  protected onDrop(event: CdkDragDrop<unknown>): void;
322
312
  protected onRemove(row: IRtDynamicSelector.ListRow<TItem>): void;
323
313
  protected onEditStart(index: number, row: IRtDynamicSelector.ListRow<TItem>): void;
324
314
  protected onEditApply(row: IRtDynamicSelector.ListRow<TItem>): void;
325
315
  protected onEditCancel(): void;
316
+ protected onReset(): void;
317
+ protected onClear(): void;
326
318
  static ɵfac: i0.ɵɵFactoryDeclaration<RtDynamicSelectorListComponent<any>, never>;
327
- static ɵcmp: i0.ɵɵComponentDeclaration<RtDynamicSelectorListComponent<any>, "rt-dynamic-selector-list", never, {
328
- "rows": {
329
- "alias": "rows";
330
- "required": false;
331
- "isSignal": true;
332
- };
333
- "draggable": {
334
- "alias": "draggable";
335
- "required": false;
336
- "isSignal": true;
337
- };
338
- "editable": {
339
- "alias": "editable";
340
- "required": false;
341
- "isSignal": true;
342
- };
343
- "disabled": {
344
- "alias": "disabled";
345
- "required": false;
346
- "isSignal": true;
347
- };
348
- "actionsShown": {
349
- "alias": "actionsShown";
350
- "required": false;
351
- "isSignal": true;
352
- };
353
- "resetClearShown": {
354
- "alias": "resetClearShown";
355
- "required": false;
356
- "isSignal": true;
357
- };
358
- "removeShown": {
359
- "alias": "removeShown";
360
- "required": false;
361
- "isSignal": true;
362
- };
363
- "resetDisabled": {
364
- "alias": "resetDisabled";
365
- "required": false;
366
- "isSignal": true;
367
- };
368
- "clearDisabled": {
369
- "alias": "clearDisabled";
370
- "required": false;
371
- "isSignal": true;
372
- };
373
- "buttonRadius": {
374
- "alias": "buttonRadius";
375
- "required": false;
376
- "isSignal": true;
377
- };
378
- "clearIcon": {
379
- "alias": "clearIcon";
380
- "required": false;
381
- "isSignal": true;
382
- };
383
- "titleWrap": {
384
- "alias": "titleWrap";
385
- "required": false;
386
- "isSignal": true;
387
- };
388
- "titleTpl": {
389
- "alias": "titleTpl";
390
- "required": false;
391
- "isSignal": true;
392
- };
393
- "controlsTpl": {
394
- "alias": "controlsTpl";
395
- "required": false;
396
- "isSignal": true;
397
- };
398
- }, {
399
- "removed": "removed";
400
- "moved": "moved";
401
- "edited": "edited";
402
- "resetClicked": "resetClicked";
403
- "cleared": "cleared";
404
- }, never, ["*"], true, never>;
319
+ static ɵcmp: i0.ɵɵComponentDeclaration<RtDynamicSelectorListComponent<any>, "rt-dynamic-selector-list", never, {}, {}, never, ["*"], true, never>;
405
320
  }
406
321
  /** Сколько ждёт поиск на сервере после последней нажатой клавиши. */
407
322
  export declare const RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE: number;
@@ -412,6 +327,11 @@ export declare const RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE: number;
412
327
  */
413
328
  export declare class RtDynamicSelectorPopupComponent<TEntity extends object> implements OnInit {
414
329
  #private;
330
+ /**
331
+ * Клавиши строк. Окно не называет строку через `aria-activedescendant`: строки — флажки и
332
+ * переключатели со своими ролями, и клавиши ведут сам фокус. Enter и пробел они отмечают сами.
333
+ */
334
+ protected readonly optionList: RtOptionList;
415
335
  protected readonly searchLabel: Signal<string>;
416
336
  protected readonly searchField: Signal<ElementRef<HTMLElement> | undefined>;
417
337
  protected readonly selectAllLabel: Signal<string>;
@@ -447,48 +367,29 @@ export declare class RtDynamicSelectorPopupComponent<TEntity extends object> imp
447
367
  protected readonly lastPinnedKey: Signal<unknown>;
448
368
  protected readonly isApplyDisabled: Signal<boolean>;
449
369
  protected readonly isNavShown: Signal<boolean>;
450
- /** Предлагаемые записи: ещё не выбранные, отсортированные селектором. */
451
- readonly entities: InputSignal<ReadonlyArray<TEntity>>;
452
- readonly keyExp: InputSignal<keyof TEntity & string>;
453
- readonly displayExp: InputSignal<keyof TEntity & string>;
454
- /** Подпись записи для строки, пункта окна и поиска; не задана — поле `displayExp`. */
455
- readonly displayWith: InputSignal<((entity: TEntity) => string) | null>;
456
- readonly mode: InputSignal<IRtDynamicSelector.Mode>;
457
- readonly multiToggleShown: InputSignalWithTransform<boolean, unknown>;
458
- readonly selectAllShown: InputSignalWithTransform<boolean, unknown>;
459
- readonly localSearch: InputSignalWithTransform<boolean, unknown>;
460
- readonly lazyLoad: InputSignalWithTransform<boolean, unknown>;
461
- readonly loading: InputSignalWithTransform<boolean, unknown>;
462
- readonly fetching: InputSignalWithTransform<boolean, unknown>;
463
- readonly pinnedKeys: InputSignal<ReadonlyArray<unknown>>;
464
- readonly navigateTitle: InputSignal<string>;
465
- readonly navigateLink: InputSignal<string>;
466
- /** Запрос, с которым выбор открывается; событием поиска он не уходит — вызывающий его знает. */
467
- readonly searchTerm: InputSignal<string>;
468
- /** Вид поля поиска — тот же вход, что у поля кита. */
469
- readonly searchAppearance: InputSignal<IRtInput.Appearance>;
470
- /** Шаг скругления поля поиска; null — скругление самого поля. */
471
- readonly searchRadius: InputSignal<TRtRadius | null>;
472
- /** Подпись пустого результата поиска; пустая строка оставляет подпись кита. */
473
- readonly emptyResultsText: InputSignal<string>;
474
- /** Подпись кнопки применения; пустая строка оставляет подпись кита. */
475
- readonly applyLabel: InputSignal<string>;
476
- /** Регистр подписи кнопки применения; `none` оставляет её как есть. */
477
- readonly applyLabelCase: InputSignal<IRtDynamicSelector.LabelCase>;
478
- /** Поле поиска получает фокус при открытии окна; по умолчанию фокус остаётся там, где был. */
479
- readonly autofocusSearch: InputSignalWithTransform<boolean, unknown>;
480
- /** Подпись пункта переносится; `false` ведёт её одной строкой с многоточием и подсказкой при обрезке. */
481
- readonly titleWrap: InputSignalWithTransform<boolean, unknown>;
482
- /** Символы подписи пункта, совпавшие со словами поиска, выделены. */
483
- readonly highlightSearch: InputSignalWithTransform<boolean, unknown>;
484
- /** Применённые ключи в порядке отметок. */
485
- readonly applied: OutputEmitterRef<unknown[]>;
486
- readonly cancelled: OutputEmitterRef<void>;
487
- /** Запрос для поиска на сервере: через паузу после последней клавиши, стёртый — пустой строкой. */
488
- readonly searchChange: OutputEmitterRef<string>;
489
- readonly loadMore: OutputEmitterRef<void>;
490
- /** Отмеченные записи: пустой список при открытии и текущие отметки после каждого поиска. */
491
- readonly temporaryChoiceChange: OutputEmitterRef<TEntity[]>;
370
+ protected readonly entities: Signal<ReadonlyArray<TEntity>>;
371
+ protected readonly keyExp: Signal<keyof TEntity & string>;
372
+ protected readonly displayExp: Signal<keyof TEntity & string>;
373
+ protected readonly displayWith: Signal<((entity: TEntity) => string) | null>;
374
+ protected readonly mode: Signal<IRtDynamicSelector.Mode>;
375
+ protected readonly multiToggleShown: Signal<boolean>;
376
+ protected readonly selectAllShown: Signal<boolean>;
377
+ protected readonly localSearch: Signal<boolean>;
378
+ protected readonly lazyLoad: Signal<boolean>;
379
+ protected readonly loading: Signal<boolean>;
380
+ protected readonly fetching: Signal<boolean>;
381
+ protected readonly pinnedKeys: Signal<ReadonlyArray<unknown>>;
382
+ protected readonly navigateTitle: Signal<string>;
383
+ protected readonly navigateLink: Signal<string>;
384
+ protected readonly searchTerm: Signal<string>;
385
+ protected readonly searchAppearance: Signal<IRtInput.Appearance>;
386
+ protected readonly searchRadius: Signal<TRtRadius | null>;
387
+ protected readonly emptyResultsText: Signal<string>;
388
+ protected readonly applyLabel: Signal<string>;
389
+ protected readonly applyLabelCase: Signal<IRtDynamicSelector.LabelCase>;
390
+ protected readonly autofocusSearch: Signal<boolean>;
391
+ protected readonly titleWrap: Signal<boolean>;
392
+ protected readonly highlightSearch: Signal<boolean>;
492
393
  ngOnInit(): void;
493
394
  protected onQueryChange(value: string | null): void;
494
395
  /** Нажатие строки флажков: при выключенном выборе нескольких без Ctrl или Cmd остаётся одна отметка. */
@@ -498,130 +399,11 @@ export declare class RtDynamicSelectorPopupComponent<TEntity extends object> imp
498
399
  protected onMultiToggle(value: boolean): void;
499
400
  protected onApply(): void;
500
401
  protected onCancel(): void;
402
+ protected onLoadMore(): void;
403
+ /** Стрелки, Home и End ведут фокус по строкам; в поле поиска Home и End остаются у курсора. */
404
+ protected onKeydown(event: KeyboardEvent): void;
501
405
  static ɵfac: i0.ɵɵFactoryDeclaration<RtDynamicSelectorPopupComponent<any>, never>;
502
- static ɵcmp: i0.ɵɵComponentDeclaration<RtDynamicSelectorPopupComponent<any>, "rt-dynamic-selector-popup", never, {
503
- "entities": {
504
- "alias": "entities";
505
- "required": false;
506
- "isSignal": true;
507
- };
508
- "keyExp": {
509
- "alias": "keyExp";
510
- "required": true;
511
- "isSignal": true;
512
- };
513
- "displayExp": {
514
- "alias": "displayExp";
515
- "required": true;
516
- "isSignal": true;
517
- };
518
- "displayWith": {
519
- "alias": "displayWith";
520
- "required": false;
521
- "isSignal": true;
522
- };
523
- "mode": {
524
- "alias": "mode";
525
- "required": false;
526
- "isSignal": true;
527
- };
528
- "multiToggleShown": {
529
- "alias": "multiToggleShown";
530
- "required": false;
531
- "isSignal": true;
532
- };
533
- "selectAllShown": {
534
- "alias": "selectAllShown";
535
- "required": false;
536
- "isSignal": true;
537
- };
538
- "localSearch": {
539
- "alias": "localSearch";
540
- "required": false;
541
- "isSignal": true;
542
- };
543
- "lazyLoad": {
544
- "alias": "lazyLoad";
545
- "required": false;
546
- "isSignal": true;
547
- };
548
- "loading": {
549
- "alias": "loading";
550
- "required": false;
551
- "isSignal": true;
552
- };
553
- "fetching": {
554
- "alias": "fetching";
555
- "required": false;
556
- "isSignal": true;
557
- };
558
- "pinnedKeys": {
559
- "alias": "pinnedKeys";
560
- "required": false;
561
- "isSignal": true;
562
- };
563
- "navigateTitle": {
564
- "alias": "navigateTitle";
565
- "required": false;
566
- "isSignal": true;
567
- };
568
- "navigateLink": {
569
- "alias": "navigateLink";
570
- "required": false;
571
- "isSignal": true;
572
- };
573
- "searchTerm": {
574
- "alias": "searchTerm";
575
- "required": false;
576
- "isSignal": true;
577
- };
578
- "searchAppearance": {
579
- "alias": "searchAppearance";
580
- "required": false;
581
- "isSignal": true;
582
- };
583
- "searchRadius": {
584
- "alias": "searchRadius";
585
- "required": false;
586
- "isSignal": true;
587
- };
588
- "emptyResultsText": {
589
- "alias": "emptyResultsText";
590
- "required": false;
591
- "isSignal": true;
592
- };
593
- "applyLabel": {
594
- "alias": "applyLabel";
595
- "required": false;
596
- "isSignal": true;
597
- };
598
- "applyLabelCase": {
599
- "alias": "applyLabelCase";
600
- "required": false;
601
- "isSignal": true;
602
- };
603
- "autofocusSearch": {
604
- "alias": "autofocusSearch";
605
- "required": false;
606
- "isSignal": true;
607
- };
608
- "titleWrap": {
609
- "alias": "titleWrap";
610
- "required": false;
611
- "isSignal": true;
612
- };
613
- "highlightSearch": {
614
- "alias": "highlightSearch";
615
- "required": false;
616
- "isSignal": true;
617
- };
618
- }, {
619
- "applied": "applied";
620
- "cancelled": "cancelled";
621
- "searchChange": "searchChange";
622
- "loadMore": "loadMore";
623
- "temporaryChoiceChange": "temporaryChoiceChange";
624
- }, never, never, true, never>;
406
+ static ɵcmp: i0.ɵɵComponentDeclaration<RtDynamicSelectorPopupComponent<any>, "rt-dynamic-selector-popup", never, {}, {}, never, never, true, never>;
625
407
  }
626
408
  /**
627
409
  * Динамический селектор: поле формы со списком выбранных записей. Значение — массив ключей в
@@ -1,6 +1,6 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ElementRef, InputSignal, Signal, WritableSignal } from "@angular/core";
3
- import { IRtIcon, TRtKitLabelMap } from "@rt-tools/ui-kit-v2/core";
3
+ import { IRtIcon, RtOptionList, TRtKitLabelMap } from "@rt-tools/ui-kit-v2/core";
4
4
  import { RtFormControlBase } from "@rt-tools/ui-kit-v2/form-control";
5
5
  import { IRtPopover, RtPopoverDirective } from "@rt-tools/ui-kit-v2/popover";
6
6
  import { IRtSelect, RtSelectTriggerDirective } from "@rt-tools/ui-kit-v2/select";
@@ -25,7 +25,6 @@ export declare class RtMultiselectComponent<TValue> extends RtFormControlBase<Re
25
25
  protected readonly placeholderText: Signal<string>;
26
26
  protected readonly popover: Signal<RtPopoverDirective>;
27
27
  protected readonly triggerEl: Signal<ElementRef<HTMLButtonElement> | undefined>;
28
- protected readonly activeIndex: WritableSignal<number>;
29
28
  /** Раскрытые ветки дерева. Живут, пока открыта панель: при открытии раскрыты ветки над выбранным. */
30
29
  protected readonly openBranches: WritableSignal<ReadonlySet<TValue>>;
31
30
  /** Дерево ли список: тогда у строк есть место под стрелку и отступ по уровню. */
@@ -35,6 +34,9 @@ export declare class RtMultiselectComponent<TValue> extends RtFormControlBase<Re
35
34
  /** Флажок каждой строки: у листа — выбран ли он, у ветки — выведен из её включённых листьев. */
36
35
  protected readonly rowChecks: Signal<ReadonlyArray<IRtSelect.TBranchState>>;
37
36
  protected readonly isOpen: Signal<boolean>;
37
+ /** Клавиатура списка: подсветка, клавиши открытия, id для `aria-activedescendant`, прокрутка к опции. */
38
+ protected readonly optionList: RtOptionList;
39
+ protected readonly activeIndex: WritableSignal<number>;
38
40
  /** Идентификатор подсвеченной опции — тот же, что уходит в `aria-activedescendant`. */
39
41
  protected readonly activeOptionId: Signal<string | null>;
40
42
  /**
@@ -69,7 +71,6 @@ export declare class RtMultiselectComponent<TValue> extends RtFormControlBase<Re
69
71
  * на саму панель: она рисуется в наложении, вне поддерева блока.
70
72
  */
71
73
  readonly panelMaxHeight: InputSignal<string | null>;
72
- constructor();
73
74
  setDisabledState(disabled: boolean): void;
74
75
  protected getEmptyValue(): ReadonlyArray<TValue>;
75
76
  protected focusAfterClear(): void;
@@ -1,37 +1,25 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ElementRef, InputSignal, InputSignalWithTransform, OutputEmitterRef, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
- import { IRtIcon, IRtInput, TRtKitLabelMap } from "@rt-tools/ui-kit-v2/core";
3
+ import { IRtIcon, IRtInput, IRtOptionTree, RtOptionList, TRtKitLabelMap } from "@rt-tools/ui-kit-v2/core";
4
4
  import { RtFormControlBase } from "@rt-tools/ui-kit-v2/form-control";
5
5
  import { IRtPopover, RtPopoverDirective } from "@rt-tools/ui-kit-v2/popover";
6
6
  import * as i1 from "@rt-tools/ui-kit-v2/radius";
7
7
  /**
8
8
  * Модель `<rt-select>`: один корневой неймспейс с префиксом `I`.
9
9
  * Generic-параметр `TValue` повторяет тип значения, который сидит в опциях.
10
+ *
11
+ * Опция и строка дерева объявлены в ядре: их раскладывают и деревья кита, а те не берут выбор из
12
+ * списка. Здесь — те же типы под прежними именами.
10
13
  */
11
14
  export declare namespace IRtSelect {
12
15
  /** Одна опция dropdown'а. */
13
- interface Option<TValue> {
14
- label: string;
15
- value: TValue;
16
- disabled?: boolean;
17
- /** Дети опции того же вида. Хотя бы одна опция с детьми делает список деревом. */
18
- children?: ReadonlyArray<Option<TValue>>;
19
- }
16
+ type Option<TValue> = IRtOptionTree.Option<TValue>;
20
17
  /** Видимая строка дерева: опция, её уровень и то, ветка ли она и раскрыта ли. */
21
- interface Row<TValue> {
22
- readonly option: Option<TValue>;
23
- readonly level: number;
24
- readonly branch: boolean;
25
- readonly open: boolean;
26
- readonly parent: TValue | null;
27
- }
18
+ type Row<TValue> = IRtOptionTree.Row<TValue>;
28
19
  /** Сколько включённых листьев ветки выбрано: все, часть или ни одного. */
29
- type TBranchState = 'all' | 'some' | 'none';
20
+ type TBranchState = IRtOptionTree.TBranchState;
30
21
  /** Что делать по боковой стрелке: какую ветку переключить и куда увести подсветку. */
31
- interface SideKeyAnswer<TValue> {
32
- readonly toggle: TValue | null;
33
- readonly index: number;
34
- }
22
+ type SideKeyAnswer<TValue> = IRtOptionTree.SideKeyAnswer<TValue>;
35
23
  /**
36
24
  * Что кит отдаёт своей разметке указателя. Три значения и не больше: большее привязало бы
37
25
  * разметку потребителя к устройству семьи, и семью стало бы не поправить, не сломав её.
@@ -75,6 +63,7 @@ export declare class RtSelectTriggerDirective<TValue = unknown> {
75
63
  static ɵfac: i0.ɵɵFactoryDeclaration<RtSelectTriggerDirective<any>, never>;
76
64
  static ɵdir: i0.ɵɵDirectiveDeclaration<RtSelectTriggerDirective<any>, "[rtSelectTrigger]", never, {}, {}, never, never, true, never>;
77
65
  }
66
+ /** Клавиши, открывающие закрытый dropdown с фокуса на trigger'е. */
78
67
  type TBooleanInput = boolean | string;
79
68
  /**
80
69
  * Single-select dropdown с опциональным filter input.
@@ -96,10 +85,12 @@ export declare class RtSelectComponent<TValue> extends RtFormControlBase<TValue
96
85
  protected readonly popover: Signal<RtPopoverDirective>;
97
86
  protected readonly triggerEl: Signal<ElementRef<HTMLButtonElement> | undefined>;
98
87
  protected readonly filterTerm: WritableSignal<string>;
99
- protected readonly activeIndex: WritableSignal<number>;
100
88
  /** Раскрытые ветки дерева. Живут, пока открыта панель: при открытии раскрыты ветки над выбранным. */
101
89
  protected readonly openBranches: WritableSignal<ReadonlySet<TValue>>;
102
90
  protected readonly isOpen: Signal<boolean>;
91
+ /** Клавиатура списка: подсветка, клавиши открытия, id для `aria-activedescendant`, прокрутка к опции. */
92
+ protected readonly optionList: RtOptionList;
93
+ protected readonly activeIndex: WritableSignal<number>;
103
94
  /** Идентификатор подсвеченной опции — тот же, что уходит в `aria-activedescendant`. */
104
95
  protected readonly activeOptionId: Signal<string | null>;
105
96
  /**
@@ -140,7 +131,6 @@ export declare class RtSelectComponent<TValue> extends RtFormControlBase<TValue
140
131
  */
141
132
  readonly panelMaxHeight: InputSignal<string | null>;
142
133
  readonly selectionChange: OutputEmitterRef<TValue | null>;
143
- constructor();
144
134
  setDisabledState(disabled: boolean): void;
145
135
  protected getEmptyValue(): TValue | null;
146
136
  protected focusAfterClear(): void;
@@ -209,56 +199,4 @@ export declare class RtSelectComponent<TValue> extends RtFormControlBase<TValue
209
199
  outputs: {};
210
200
  }]>;
211
201
  }
212
- /**
213
- * Держит подсвеченную клавишами опцию в видимой части панели.
214
- *
215
- * Панель списка ограничена по высоте, и длинный список прокручивается внутри неё. Клавиши двигают
216
- * подсветку, но фокус остаётся на поле: браузер сам панель не прокручивает, и подсветка уходила
217
- * за нижний край — человек выбирал Enter'ом то, чего не видел. После каждой отрисовки, в которой
218
- * сменилась подсвеченная опция, она прокручивается ровно настолько, чтобы встать в панель.
219
- *
220
- * Панель рисуется в наложении, вне поддерева семьи, поэтому опция ищется в документе по своему
221
- * идентификатору — тому же, что стоит в `aria-activedescendant`. На сервере отрисовки нет, и
222
- * эффект не выполняется; среда без `scrollIntoView` пропускается.
223
- *
224
- * Зовётся в контексте внедрения — полем или конструктором семьи.
225
- *
226
- * @param activeOptionId идентификатор подсвеченной опции; `null` — подсветки нет или панель закрыта
227
- */
228
- export declare function rtScrollActiveOptionIntoView(activeOptionId: () => string | null): void;
229
- /**
230
- * Дерево опций выбора из списка — общее для `rt-select` и `rt-multiselect`.
231
- *
232
- * Обе семьи раскладывают, ищут и считают дерево одинаково, поэтому это чистые функции в одном
233
- * месте: две копии разошлись бы на первой правке. Состояние — какие ветки раскрыты — живёт в семье,
234
- * здесь только расчёт по нему.
235
- */
236
- type TOption<TValue> = IRtSelect.Option<TValue>;
237
- type TRow<TValue> = IRtSelect.Row<TValue>;
238
- /** Список — дерево, если хоть у одной опции есть дети. Плоский список рисуется как прежде. */
239
- export declare function rtTreeIsTree<TValue>(options: ReadonlyArray<TOption<TValue>>): boolean;
240
- /** Опция по значению на любой глубине. */
241
- export declare function rtTreeFind<TValue>(options: ReadonlyArray<TOption<TValue>>, value: TValue): TOption<TValue> | undefined;
242
- /**
243
- * Включённые листья под опцией; у самого листа — он сам. Отключённая ветка не отдаёт никого: её
244
- * листья выбрать нельзя, как и её саму.
245
- */
246
- export declare function rtTreeLeaves<TValue>(option: TOption<TValue>): ReadonlyArray<TValue>;
247
- /** Сколько включённых листьев ветки выбрано. Флажок ветки выводится из этого, а не хранится. */
248
- export declare function rtTreeBranchState<TValue>(option: TOption<TValue>, chosen: ReadonlyArray<TValue>): IRtSelect.TBranchState;
249
- /** Ветки, под которыми лежит выбранное значение: они раскрыты, когда список открывается. */
250
- export declare function rtTreeOpenFor<TValue>(options: ReadonlyArray<TOption<TValue>>, chosen: ReadonlyArray<TValue>): ReadonlySet<TValue>;
251
- /**
252
- * Видимые строки по уровням. Без поискового слова раскрыты ветки из `open`. Со словом строка
253
- * остаётся, если совпала она сама или кто-то под ней, и путь к совпадению показан раскрытым.
254
- * Ветка, совпавшая сама, держит детей такими, какими они были.
255
- */
256
- export declare function rtTreeRows<TValue>(options: ReadonlyArray<TOption<TValue>>, open: ReadonlySet<TValue>, rawTerm?: string): ReadonlyArray<TRow<TValue>>;
257
- /**
258
- * Ответ на боковую стрелку. Вправо: свёрнутая ветка раскрывается, раскрытая уводит подсветку на
259
- * первого ребёнка. Влево: раскрытая ветка сворачивается, иначе подсветка уходит на родителя.
260
- */
261
- export declare function rtTreeSideKey<TValue>(rows: ReadonlyArray<TRow<TValue>>, index: number, key: string): IRtSelect.SideKeyAnswer<TValue>;
262
- /** Набор раскрытых веток с переключённой одной. */
263
- export declare function rtTreeToggle<TValue>(open: ReadonlySet<TValue>, value: TValue): ReadonlySet<TValue>;
264
202
  export {};
@@ -0,0 +1,34 @@
1
+ import * as i0 from "@angular/core";
2
+ import { InputSignal } from "@angular/core";
3
+ import { IRtServiceLogo } from "@rt-tools/ui-kit-v2/service-logo";
4
+ /**
5
+ * Блок службы — первый блок тела панели настройки подключения: знак службы размера `md`, справа
6
+ * имя службы и строка-описание, под блоком черта. Одна разметка на интеграции, способы оплаты и
7
+ * мессенджеры. Своих текстов блок не несёт: имя, описание и подписи знаков даёт приложение.
8
+ */
9
+ export declare class RtServiceBlockComponent {
10
+ /** Знаки службы — те же, что принимает `rt-service-logo`; несколько ложатся внахлёст. */
11
+ readonly logos: InputSignal<readonly IRtServiceLogo.Item[]>;
12
+ /** Имя службы — жирная строка справа от знака. */
13
+ readonly name: InputSignal<string>;
14
+ /** Строка-описание под именем. Пустая строка не рисуется. */
15
+ readonly description: InputSignal<string>;
16
+ static ɵfac: i0.ɵɵFactoryDeclaration<RtServiceBlockComponent, never>;
17
+ static ɵcmp: i0.ɵɵComponentDeclaration<RtServiceBlockComponent, "rt-service-block", never, {
18
+ "logos": {
19
+ "alias": "logos";
20
+ "required": true;
21
+ "isSignal": true;
22
+ };
23
+ "name": {
24
+ "alias": "name";
25
+ "required": true;
26
+ "isSignal": true;
27
+ };
28
+ "description": {
29
+ "alias": "description";
30
+ "required": false;
31
+ "isSignal": true;
32
+ };
33
+ }, {}, never, never, true, never>;
34
+ }
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ElementRef, EnvironmentProviders, InjectionToken, InputSignal, InputSignalWithTransform, OutputEmitterRef, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
3
  import { FormControl } from "@angular/forms";
4
- import { IRtIcon, IRtInput } from "@rt-tools/ui-kit-v2/core";
4
+ import { IRtIcon, IRtInput, IRtMatchPart } from "@rt-tools/ui-kit-v2/core";
5
5
  /**
6
6
  * Входы вида бокового меню: подписи и заливка значков, поле поиска, подсказка прокрутки панели. Ни
7
7
  * один не меняет поведения — по ним приложение даёт меню вид первого кита, а без них меню рисуется
@@ -113,11 +113,8 @@ export declare namespace IRtSideMenu {
113
113
  data?: ItemData;
114
114
  };
115
115
  }
116
- /** Кусок подписи: отмеченный — тот, которым она совпала с запросом. */
117
- interface TitlePart {
118
- text: string;
119
- matched: boolean;
120
- }
116
+ /** Кусок подписи: отмеченный — тот, которым она совпала с запросом. Объявлен в ядре. */
117
+ type TitlePart = IRtMatchPart;
121
118
  }
122
119
  /** Шапка бокового меню: над полосой пунктов. */
123
120
  export declare class RtSideMenuHeaderDirective {
@@ -368,12 +365,12 @@ export declare class RtSideMenuComponent extends RtSideMenuLookBase implements I
368
365
  }, ["headerTpl", "footerTpl", "ownIconTpl"], never, true, never>;
369
366
  }
370
367
  /**
371
- * Отбор пунктов подменю по подстроке подписи.
368
+ * Отбор пунктов подменю по подписи — правилом поиска кита: каждое слово запроса в любом порядке.
372
369
  *
373
370
  * Отбор спускается внутрь папок на любую глубину: потребитель кладёт в папки то, что человек и ищет
374
371
  * по имени, и по одному верхнему уровню такой пункт не нашёлся бы.
375
372
  *
376
- * В выдаче стоят только строки, содержащие запрос. Папка остаётся путём к совпавшим детям, а её
373
+ * В выдаче стоят только строки, совпавшие с запросом. Папка остаётся путём к совпавшим детям, а её
377
374
  * состав отбирается тем же правилом: иначе одно совпадение по имени папки вытаскивало бы весь её
378
375
  * состав. Папка, совпавшая только по имени, остаётся одной строкой без детей.
379
376
  *
@@ -396,18 +393,6 @@ export declare const RT_SIDE_MENU_WIDTH_MAX: number;
396
393
  export declare const RT_SIDE_MENU_WIDTH_STEP: number;
397
394
  /** Приведение ширины к пределам. */
398
395
  export declare function clampSideMenuWidth(width: number): number;
399
- /**
400
- * Резка подписи на совпавшие и несовпавшие куски.
401
- *
402
- * Отмечаются все вхождения: отмеченное одно первое читается как «второго нет». Сравнение без учёта
403
- * регистра, а куски режутся из оригинала — приведение к нижнему регистру переписало бы названия.
404
- */
405
- export declare function splitSideMenuTitle(name: string, query: string): IRtSideMenu.TitlePart[];
406
- /**
407
- * Резка подписи по каждому слову запроса. Приложение делит поиск по пробелам и ищет каждое слово
408
- * отдельно, поэтому и отмечено каждое. Слово внутри уже отмеченного куска не режет его второй раз.
409
- */
410
- export declare function splitTitleByWords(name: string, query: string): IRtSideMenu.TitlePart[];
411
396
  /**
412
397
  * Пункты подменю в том порядке, в каком они стоят на экране. Внутрь папки список спускается, только
413
398
  * если та раскрыта: ходьба стрелками идёт по видимому, а не по всему набору.