@rt-tools/ui-kit-v2 0.28.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +2 -2
  2. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-container.mjs +9 -4
  4. package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +37 -4
  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-date-picker.mjs +1 -1
  10. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +1 -1
  12. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +2 -2
  14. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +1 -1
  16. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +2 -2
  18. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +367 -23
  20. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs +2 -2
  22. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +4 -0
  24. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +2 -2
  26. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  27. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +4 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  29. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +2 -2
  30. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -1
  31. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +2 -2
  32. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  33. package/package.json +1 -1
  34. package/src/lib/components/calendar/rt-calendar.component.scss +3 -2
  35. package/src/lib/components/container/CONTEXT.md +6 -0
  36. package/src/lib/components/container/rt-container.component.scss +4 -0
  37. package/src/lib/components/data-list/toolbar/rt-data-list-toolbar.component.scss +1 -1
  38. package/src/lib/components/dynamic-list/rt-dynamic-list.component.scss +1 -1
  39. package/src/lib/components/filter-control/rt-filter-control.component.scss +4 -2
  40. package/src/lib/components/page-header/CONTEXT.md +12 -0
  41. package/src/lib/components/page-header/more/rt-page-header-more.component.scss +7 -0
  42. package/src/lib/components/page-header/rt-page-header-mobile.scss +24 -0
  43. package/src/lib/components/page-header/rt-page-header.component.scss +25 -3
  44. package/src/lib/components/pdf-viewer/rt-pdf-viewer.component.scss +1 -1
  45. package/src/lib/components/popover/CONTEXT.md +2 -1
  46. package/src/lib/components/toolbar/rt-toolbar.component.scss +3 -1
  47. package/src/lib/components/workspace/rt-workspace.component.scss +8 -6
  48. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +5 -3
  49. package/src/styles/_breakpoints.scss +19 -0
  50. package/src/styles/_index.scss +4 -0
  51. package/src/styles/_place.scss +7 -0
  52. package/styles/tokens.css +8 -0
  53. package/types/rt-tools-ui-kit-v2-core.d.ts +24 -5
  54. package/types/rt-tools-ui-kit-v2-page-header.d.ts +60 -6
  55. package/types/rt-tools-ui-kit-v2-table.d.ts +4 -0
@@ -1,3 +1,5 @@
1
+ @use '../../../../styles/breakpoints' as bp;
2
+
1
3
  @layer rt-kit.components {
2
4
  .rt-chat {
3
5
  --rt-chat-bubble-radius: var(--rt-radius-lg);
@@ -37,9 +39,9 @@
37
39
  &--expanded > .rt-file-drop {
38
40
  block-size: 100%;
39
41
 
40
- // На широких экранах чат не растягивается на весь вьюпорт: тред и
41
- // композер иначе разрежены. Свыше 1440px фиксируем колонку по центру.
42
- @media (width >= 1441px) {
42
+ // На широком месте чат не растягивается во всю ширину: тред и композер иначе
43
+ // разрежены. Шире 1440px колонка стоит по центру.
44
+ @include bp.place-min(1440px) {
43
45
  inline-size: 1000px;
44
46
  margin-inline: auto;
45
47
  max-inline-size: 100%;
@@ -5,3 +5,22 @@ $rt-bp-sm: 480px !default;
5
5
  $rt-bp-md: 768px !default;
6
6
  $rt-bp-lg: 1080px !default;
7
7
  $rt-bp-xl: 1380px !default;
8
+
9
+ // Место страницы — контейнер с именем `rt-place`. Его объявляют корень документа и
10
+ // `rt-container`: компонент внутри контейнера считает порог от его ширины, вне его — от корня,
11
+ // то есть от окна. Имя записано буквами: линтер стилей не читает имя из переменной.
12
+
13
+ // Порог по ширине места: `@include bp.place-max(bp.$rt-bp-md) { … }`. Окна и панели поверх
14
+ // экрана сюда не идут: они лежат вне места страницы и остаются на `@media`.
15
+ @mixin place-max($width) {
16
+ @container rt-place (width <= #{$width}) {
17
+ @content;
18
+ }
19
+ }
20
+
21
+ // Шире порога по месту — пара к `place-max`.
22
+ @mixin place-min($width) {
23
+ @container rt-place (width > #{$width}) {
24
+ @content;
25
+ }
26
+ }
@@ -43,6 +43,10 @@
43
43
  // раскладку у себя, ради чего словарь и переехал в кит.
44
44
  @forward './form';
45
45
 
46
+ // Запасное место страницы на корне документа: без него порог по месту у компонента вне
47
+ // `rt-container` не нашёл бы контейнера и не сработал.
48
+ @forward './place';
49
+
46
50
  // Стили директивы кнопки: своего представления у директивы нет, поэтому её `.scss` не
47
51
  // подключён ни одним `styleUrl`. Без этой строки потребитель, взявший `tokens.css` по
48
52
  // инструкции README, получает `rtButton`, нарисованный браузерной кнопкой.
@@ -0,0 +1,7 @@
1
+ /* Корень документа — запасное место страницы. Компонент кита считает пороги от ближайшего
2
+ места по имени: внутри `rt-container` от его ширины, вне его от корня, а ширина корня равна
3
+ окну. Так потребитель без контейнера видит пороги окна, как раньше. Объявление стоит вне
4
+ слоя, как и свойства на корне: потребитель перебивает его порядком. */
5
+ :root {
6
+ container: rt-place / inline-size;
7
+ }
package/styles/tokens.css CHANGED
@@ -6799,6 +6799,14 @@ html.rt-theme-dark.rt-preset-material {
6799
6799
  }
6800
6800
  }
6801
6801
  }
6802
+ /* Корень документа — запасное место страницы. Компонент кита считает пороги от ближайшего
6803
+ места по имени: внутри `rt-container` от его ширины, вне его от корня, а ширина корня равна
6804
+ окну. Так потребитель без контейнера видит пороги окна, как раньше. Объявление стоит вне
6805
+ слоя, как и свойства на корне: потребитель перебивает его порядком. */
6806
+ :root {
6807
+ container: rt-place/inline-size;
6808
+ }
6809
+
6802
6810
  @layer rt-kit.components {
6803
6811
  .rt-button {
6804
6812
  /* Высота приходит общей шкалой контролов, а не своим числом: кнопка, поле и
@@ -669,6 +669,7 @@ export declare const RT_KIT_LABELS_EN: {
669
669
  readonly uiMoveStage: "Move";
670
670
  readonly uiMoveStageAria: "Move stage";
671
671
  readonly uiNavMenu: "Navigation menu";
672
+ readonly uiNavMore: "More";
672
673
  readonly uiNavUnread: "Unread";
673
674
  readonly uiNextMonth: "Next month";
674
675
  readonly uiNextPage: "Next page";
@@ -863,10 +864,19 @@ export declare class RtKitLabelPipe implements PipeTransform {
863
864
  static ɵfac: i0.ɵɵFactoryDeclaration<RtKitLabelPipe, never>;
864
865
  static ɵpipe: i0.ɵɵPipeDeclaration<RtKitLabelPipe, "rtKitLabel", true>;
865
866
  }
867
+ /** Порог узкого вида — тот же, что у `$rt-bp-lg` в стилях кита. */
868
+ export declare const RT_NARROW_WIDTH: number;
869
+ /**
870
+ * Узок ли вид. Ширина места страницы решает, когда место объявлено; без него решает окно.
871
+ */
872
+ export declare function rtNarrowByWidth(placeWidth: number | null, viewportNarrow: boolean): boolean;
866
873
  /**
867
874
  * Обёртка над CDK `BreakpointObserver` — публикует reactive signals для
868
875
  * mobile/tablet/desktop матчей. `toSignal()` обёртывает CDK Observable в Signal
869
876
  * с `initialValue` для CSR-safe рендера.
877
+ *
878
+ * Узкий вид считается от ширины места страницы: его объявляет `rt-container`, и рядом с
879
+ * боковой панелью место уже окна. Без объявленного места вид считается от окна.
870
880
  */
871
881
  export declare class BreakpointsService {
872
882
  #private;
@@ -874,13 +884,22 @@ export declare class BreakpointsService {
874
884
  readonly tablet: Signal<boolean>;
875
885
  readonly desktop: Signal<boolean>;
876
886
  /**
877
- * Узкий вьюпорт (≤1080px, планшет + мобила) — единый порог для компонентов,
878
- * которые на узком экране подменяют развёрнутый контрол на компактный
879
- * (напр. `rt-filter-control`: сегменты → `rt-select`). Совпадает с
880
- * брейкпоинтом 1080px из SCSS-конвенции кита. `initialValue: false` — на
881
- * SSR/CSR до первого matchMedia рендерим desktop-вариант.
887
+ * Узкое окно (≤1080px). Его читает то, что открывается поверх экрана и занимает окно:
888
+ * выбор между всплывающим окном и листом снизу, подсказки списка в окне выбора.
889
+ * `initialValue: false` — на SSR/CSR до первого matchMedia рендерим desktop-вариант.
890
+ */
891
+ readonly viewportNarrow: Signal<boolean>;
892
+ /**
893
+ * Узкий вид (≤1080px) — единый порог для компонентов, которые на узком месте подменяют
894
+ * развёрнутый контрол на компактный (напр. `rt-filter-control`: сегменты → `rt-select`).
895
+ * Считается от ширины места страницы, без места — от окна.
882
896
  */
883
897
  readonly narrow: Signal<boolean>;
898
+ /**
899
+ * Объявляет узел местом страницы и возвращает снятие. Без `ResizeObserver` (сервер
900
+ * отрисовки) место не объявляется, и вид считается от окна.
901
+ */
902
+ registerPlace(element: HTMLElement): () => void;
884
903
  static ɵfac: i0.ɵɵFactoryDeclaration<BreakpointsService, never>;
885
904
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
886
905
  }
@@ -1,6 +1,6 @@
1
1
  import { BooleanInput, NumberInput } from "@angular/cdk/coercion";
2
2
  import * as i0 from "@angular/core";
3
- import { InputSignal, InputSignalWithTransform, OutputEmitterRef, Signal, TemplateRef, WritableSignal } from "@angular/core";
3
+ import { ElementRef, InputSignal, InputSignalWithTransform, OutputEmitterRef, Signal, TemplateRef, WritableSignal } from "@angular/core";
4
4
  import { IRtIcon, TRtKitLabelMap, TRtKitTranslator } from "@rt-tools/ui-kit-v2/core";
5
5
  import { RtPopoverDirective } from "@rt-tools/ui-kit-v2/popover";
6
6
  export declare namespace IRtPageHeader {
@@ -31,6 +31,13 @@ export declare namespace IRtPageHeader {
31
31
  readonly unread?: boolean;
32
32
  /** Панель второго уровня: колонка → группа → пункт. */
33
33
  readonly columns?: ReadonlyArray<Column>;
34
+ /**
35
+ * Важность раздела верхнего ряда: в какой очереди он уходит в пункт «Ещё», когда ряду
36
+ * не хватает ширины. Чем меньше число, тем раньше раздел уходит. По умолчанию `0`; среди
37
+ * разделов с равной важностью первым уходит стоящий дальше от начала списка. У пункта
38
+ * панели поле не читается.
39
+ */
40
+ readonly priority?: number;
34
41
  }
35
42
  /** Колонка панели. Ширина панели считается числом колонок, а не содержимым. */
36
43
  interface Column {
@@ -90,6 +97,31 @@ declare namespace IRtPageHeaderView {
90
97
  readonly panelItems: ReadonlyArray<Entry>;
91
98
  /** Группы всех колонок подряд: на узком экране колонок нет, а группы есть. */
92
99
  readonly panelGroups: ReadonlyArray<Group>;
100
+ /** Очередь ухода в «Ещё»: меньшее число уходит раньше. */
101
+ readonly priority: number;
102
+ }
103
+ }
104
+ declare namespace IRtPageHeaderFit {
105
+ /** Раздел верхнего ряда с замеренной шириной и важностью. */
106
+ interface Slot {
107
+ readonly id: string;
108
+ readonly width: number;
109
+ readonly priority: number;
110
+ }
111
+ interface Input {
112
+ /** Разделы в порядке списка. */
113
+ readonly slots: ReadonlyArray<Slot>;
114
+ /** Ширина пункта «Ещё». */
115
+ readonly moreWidth: number;
116
+ /** Ширина, которую ряд может занять. */
117
+ readonly available: number;
118
+ /** Промежуток между соседними пунктами ряда. */
119
+ readonly gap: number;
120
+ }
121
+ /** Раскладка ряда: оба списка идут в порядке исходного списка. */
122
+ interface Result {
123
+ readonly row: ReadonlyArray<string>;
124
+ readonly more: ReadonlyArray<string>;
93
125
  }
94
126
  }
95
127
  /** Пункты панели одним списком — колонки и группы для этого раскрываются. */
@@ -108,11 +140,6 @@ declare function toSections(items: ReadonlyArray<IRtPageHeader.Item>): ReadonlyA
108
140
  /** Адрес без строки запроса и якоря — подсветка считается по пути. */
109
141
  declare function pathOf(url: string): string;
110
142
  declare function isEntryActive(entry: IRtPageHeaderView.Entry, path: string): boolean;
111
- /**
112
- * Разделы, у которых активен хоть один пункт панели. Обход идёт по раскрытому
113
- * списку пунктов: своего адреса у раздела с панелью нет, и подсветить его больше
114
- * нечем.
115
- */
116
143
  /**
117
144
  * Разделы для кругов сжатой полосы: первые `count` из тех, у кого есть иконка. Раздел без
118
145
  * иконки в круг не попадает — показать в нём нечего, и он остаётся под кнопкой «ещё».
@@ -124,7 +151,23 @@ declare function compactSectionsOf(sections: ReadonlyArray<IRtPageHeaderView.Sec
124
151
  * из области целиком, прилипшим не считается: его не видно вовсе.
125
152
  */
126
153
  declare function isStuck(intersectionRatio: number, isIntersecting: boolean): boolean;
154
+ /**
155
+ * Разделы, у которых активен хоть один пункт панели. Обход идёт по раскрытому
156
+ * списку пунктов: своего адреса у раздела с панелью нет, и подсветить его больше
157
+ * нечем.
158
+ */
127
159
  declare function activeSectionIds(sections: ReadonlyArray<IRtPageHeaderView.Section>, url: string): ReadonlySet<string>;
160
+ /**
161
+ * Какие разделы стоят в ряду, а какие уходят в «Ещё». Всё помещается — «Ещё» нет. Иначе разделы
162
+ * уходят по очереди важности, пока оставшиеся вместе с «Ещё» не встанут в доступную ширину:
163
+ * меньшая важность уходит раньше, а при равной — стоящий дальше от начала списка. Порядок
164
+ * оставшихся не меняется.
165
+ */
166
+ declare function fitRow(input: IRtPageHeaderFit.Input): IRtPageHeaderFit.Result;
167
+ /** Активен ли раздел: своим адресом или адресом пункта своей панели. */
168
+ declare function isSectionActive(section: IRtPageHeaderView.Section, path: string): boolean;
169
+ /** Есть ли среди разделов активный — по нему «Ещё» подсвечивается, как выбранный пункт ряда. */
170
+ declare function hasActiveSection(sections: ReadonlyArray<IRtPageHeaderView.Section>, url: string): boolean;
128
171
  /**
129
172
  * Верхняя горизонтальная плашка-навигация для первого уровня доменных страниц.
130
173
  *
@@ -141,6 +184,9 @@ declare function activeSectionIds(sections: ReadonlyArray<IRtPageHeaderView.Sect
141
184
  */
142
185
  export declare class RtPageHeaderComponent {
143
186
  #private;
187
+ protected readonly navRef: Signal<ElementRef<HTMLElement> | undefined>;
188
+ protected readonly listRef: Signal<ElementRef<HTMLElement> | undefined>;
189
+ protected readonly moreItemRef: Signal<ElementRef<HTMLElement> | undefined>;
144
190
  /** Переводчик для чистого пайпа подписи: шаблон отдаёт его вторым доводом. */
145
191
  protected readonly translate: Signal<TRtKitTranslator>;
146
192
  protected readonly t: Signal<TRtKitLabelMap>;
@@ -151,6 +197,14 @@ export declare class RtPageHeaderComponent {
151
197
  protected readonly compact: Signal<boolean>;
152
198
  /** Разделы в кругах сжатой полосы: первые с иконкой, число — по входу. */
153
199
  protected readonly compactSections: Signal<ReadonlyArray<IRtPageHeaderView.Section>>;
200
+ /** Разделы, ушедшие из ряда в «Ещё»: шаблон вынимает их из ряда, сохраняя в разметке для замера. */
201
+ protected readonly overflowIds: Signal<ReadonlySet<string>>;
202
+ /** Разделы панели «Ещё» в порядке списка. */
203
+ protected readonly moreSections: Signal<ReadonlyArray<IRtPageHeaderView.Section>>;
204
+ /** «Ещё» стоит в ряду, только когда в ряд не встал хоть один раздел. */
205
+ protected readonly moreShown: Signal<boolean>;
206
+ /** Выбранный раздел ушёл в «Ещё» — подсвечивается сам «Ещё». */
207
+ protected readonly moreActive: Signal<boolean>;
154
208
  /** Форма пункта решается один раз здесь, а не ветвлениями в шаблоне. */
155
209
  protected readonly sections: Signal<ReadonlyArray<IRtPageHeaderView.Section>>;
156
210
  /**
@@ -65,6 +65,10 @@ export declare class RtCopyCellComponent {
65
65
  *
66
66
  * Ширина известна только отрисованному узлу, а меняется она и от переезда столбца, и от
67
67
  * ширины окна: посчитанная один раз при заведении, она соврала бы при первом же изменении.
68
+ *
69
+ * Браузер шлёт `mouseenter` сперва ячейке, потом её содержимому, и перерисовки между ними
70
+ * нет. Подсказка читает свой текст на входе указателя в содержимое, поэтому текст отдаётся
71
+ * ей сразу: иначе она застала бы прежний, пустой, и появилась бы только со второго наведения.
68
72
  */
69
73
  protected measureTruncation(): void;
70
74
  protected onCopy(event: MouseEvent): void;