@rt-tools/ui-kit-v2 0.16.0 → 0.17.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 (53) hide show
  1. package/README.md +7 -0
  2. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +96 -41
  3. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  4. package/fesm2022/rt-tools-ui-kit-v2.mjs +1106 -451
  5. package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
  6. package/package.json +1 -1
  7. package/rt-tools-ui-kit-v2-0.17.0.tgz +0 -0
  8. package/src/lib/components/action-bar/CONTEXT.md +5 -0
  9. package/src/lib/components/action-bar/rt-action-bar.component.scss +30 -16
  10. package/src/lib/components/aside/CONTEXT.md +9 -1
  11. package/src/lib/components/aside/footer/rt-aside-footer.component.scss +7 -8
  12. package/src/lib/components/aside/header/rt-aside-header.component.scss +16 -1
  13. package/src/lib/components/aside/rt-aside.component.scss +17 -1
  14. package/src/lib/components/button/CONTEXT.md +12 -11
  15. package/src/lib/components/button/rt-button.directive.scss +36 -0
  16. package/src/lib/components/data-list/settings/rt-data-list-settings-aside.component.scss +2 -2
  17. package/src/lib/components/data-table/cell/rt-data-table-cell.component.scss +1 -1
  18. package/src/lib/components/data-table/filter-cell/rt-data-table-filter-cell.component.scss +1 -1
  19. package/src/lib/components/data-table/rt-data-table.component.scss +1 -1
  20. package/src/lib/components/dialog/CONTEXT.md +9 -0
  21. package/src/lib/components/dialog/content/rt-dialog-content.component.scss +20 -0
  22. package/src/lib/components/dialog/footer/rt-dialog-footer.component.scss +18 -2
  23. package/src/lib/components/dialog/header/rt-dialog-header.component.scss +21 -3
  24. package/src/lib/components/dialog/rt-dialog.component.scss +9 -3
  25. package/src/lib/components/dynamic-selector/CONTEXT.md +6 -0
  26. package/src/lib/components/header/CONTEXT.md +2 -2
  27. package/src/lib/components/icon/CONTEXT.md +11 -7
  28. package/src/lib/components/icon/rt-icon.component.scss +47 -0
  29. package/src/lib/components/icon-button/CONTEXT.md +27 -20
  30. package/src/lib/components/icon-button/rt-icon-button.component.scss +51 -25
  31. package/src/lib/components/image-upload/CONTEXT.md +20 -15
  32. package/src/lib/components/image-upload/rt-image-upload.component.scss +14 -2
  33. package/src/lib/components/pagination/rt-pagination.component.scss +1 -1
  34. package/src/lib/components/scroll-area/CONTEXT.md +2 -0
  35. package/src/lib/components/scroll-area/rt-scroll-area.component.scss +20 -3
  36. package/src/lib/components/side-menu/CONTEXT.md +7 -2
  37. package/src/lib/components/spinner/CONTEXT.md +15 -8
  38. package/src/lib/components/spinner/rt-spinner.component.scss +108 -9
  39. package/src/lib/components/tag/rt-tag.component.scss +43 -23
  40. package/src/lib/components/toast/CONTEXT.md +8 -0
  41. package/src/lib/components/toast/rt-toast.component.scss +74 -15
  42. package/src/lib/components/toast/rt-toaster.component.scss +5 -1
  43. package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +35 -37
  44. package/src/lib/components/toggle-switch/CONTEXT.md +11 -3
  45. package/src/lib/components/toggle-switch/rt-toggle-switch.component.scss +53 -14
  46. package/src/lib/components/toolbar/rt-toolbar.component.scss +15 -4
  47. package/src/lib/components/tooltip/CONTEXT.md +5 -5
  48. package/src/rich-editor/lib/components/chat/CONTEXT.md +7 -2
  49. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +25 -0
  50. package/styles/tokens.css +35 -0
  51. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +16 -20
  52. package/types/rt-tools-ui-kit-v2.d.ts +371 -62
  53. package/rt-tools-ui-kit-v2-0.16.0.tgz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rt-tools/ui-kit-v2",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Yauheni Krumin",
6
6
  "type": "module",
Binary file
@@ -38,6 +38,11 @@
38
38
  всегда, и признак значка стоит модификатором — условие в шаблоне было бы оформлением, уехавшим
39
39
  в код.
40
40
 
41
+ - **Меню действия со списком живёт в оверлее, вне полосы.** Свойства полосы до него не доходят,
42
+ поэтому `--rt-action-bar-menu-*` читаются с запасным значением и задаются на корне страницы. Без
43
+ них меню скруглено ступенью `md` и отбрасывает тень карточки.
44
+ - **Цвета, отступы и шрифт полосы — свойства блока** `--rt-action-bar-*` со значениями прежнего вида.
45
+
41
46
  ## Края
42
47
 
43
48
  - Ноль выбранного показан числом: счётчик, прячущийся на нуле, дёргал бы ширину полосы ровно в
@@ -7,12 +7,19 @@
7
7
  .rt-action-bar {
8
8
  --rt-action-bar-radius: var(--rt-radius-lg);
9
9
  --rt-action-bar-shadow: var(--rt-shadow-card);
10
+ --rt-action-bar-bg: var(--rt-color-bg-inverse);
11
+ --rt-action-bar-color: var(--rt-color-text-inverse);
12
+ --rt-action-bar-padding: var(--rt-space-2) var(--rt-space-4);
13
+ --rt-action-bar-gap: var(--rt-space-4);
14
+ --rt-action-bar-font-size: var(--rt-text-sm);
15
+ --rt-action-bar-counter-weight: var(--rt-font-weight-medium);
10
16
  --rt-action-bar-action-radius: var(--rt-radius-md);
11
- --rt-action-bar-action-bg-hover: color-mix(in srgb, var(--rt-color-text-inverse) 16%, transparent);
17
+ --rt-action-bar-action-padding-block: var(--rt-space-1);
18
+ --rt-action-bar-action-padding-inline: var(--rt-space-2);
19
+ --rt-action-bar-action-weight: var(--rt-font-weight-medium);
20
+ --rt-action-bar-action-bg-hover: color-mix(in srgb, var(--rt-action-bar-color) 16%, transparent);
12
21
  --rt-action-bar-action-color-danger: var(--rt-color-action-danger-on-surface);
13
22
  --rt-action-bar-action-focus-shadow: var(--rt-shadow-focus-ring);
14
- --rt-action-bar-menu-radius: var(--rt-radius-md);
15
- --rt-action-bar-menu-shadow: var(--rt-shadow-card);
16
23
 
17
24
  // Предел ширины стоит и на самом элементе. Содержащий блок полосы — этот элемент, и
18
25
  // без предела он растёт по содержимому: сто процентов считались бы тогда от выросшего,
@@ -22,16 +29,16 @@
22
29
  max-width: 100%;
23
30
  box-sizing: border-box;
24
31
  align-items: center;
25
- padding: var(--rt-space-2) var(--rt-space-4);
32
+ padding: var(--rt-action-bar-padding);
26
33
  border-radius: var(--rt-action-bar-radius);
27
- background: var(--rt-color-bg-inverse);
34
+ background: var(--rt-action-bar-bg);
28
35
  box-shadow: var(--rt-action-bar-shadow);
29
- color: var(--rt-color-text-inverse);
30
- font-size: var(--rt-text-sm);
31
- gap: var(--rt-space-4);
36
+ color: var(--rt-action-bar-color);
37
+ font-size: var(--rt-action-bar-font-size);
38
+ gap: var(--rt-action-bar-gap);
32
39
 
33
40
  &__counter {
34
- font-weight: var(--rt-font-weight-medium);
41
+ font-weight: var(--rt-action-bar-counter-weight);
35
42
  white-space: nowrap;
36
43
  }
37
44
 
@@ -47,7 +54,7 @@
47
54
  &__action {
48
55
  display: flex;
49
56
  align-items: center;
50
- padding: var(--rt-space-1) var(--rt-space-2);
57
+ padding: var(--rt-action-bar-action-padding-block) var(--rt-action-bar-action-padding-inline);
51
58
  border: 0;
52
59
  border-radius: var(--rt-action-bar-action-radius);
53
60
  background: transparent;
@@ -58,7 +65,7 @@
58
65
 
59
66
  // Нажатие в этом ките набрано средним начертанием — так набрана кнопка кита, и
60
67
  // действие полосы такое же нажатие. Первый кит ставил здесь шестьсот.
61
- font-weight: var(--rt-font-weight-medium);
68
+ font-weight: var(--rt-action-bar-action-weight);
62
69
  gap: var(--rt-space-2);
63
70
 
64
71
  &:hover {
@@ -94,21 +101,28 @@
94
101
  // белому, и крестика не было видно ни в одном кадре. Своё свойство блока перебивают —
95
102
  // так делает просмотр фотографии, где кнопка стоит на снимке.
96
103
  &__close {
97
- --rt-icon-button-color: var(--rt-color-text-inverse);
104
+ --rt-icon-button-color: var(--rt-action-bar-color);
98
105
  --rt-icon-button-color-bg-hover: var(--rt-action-bar-action-bg-hover);
99
106
 
100
107
  flex: none;
101
108
  margin-left: auto;
102
109
  }
103
110
 
111
+ // Меню рисуется в оверлее, вне полосы: объявление на полосе до него не доходит, и раньше
112
+ // меню выходило без скругления и тени. Свои свойства меню читает с запасным значением —
113
+ // объявленное на самом меню перебило бы правило приложения на корне страницы, а только
114
+ // оттуда свойство до оверлея и доходит.
104
115
  &__menu {
116
+ --rt-action-bar-menu-radius-default: var(--rt-radius-md);
117
+ --rt-action-bar-menu-shadow-default: var(--rt-shadow-card);
118
+
105
119
  display: flex;
106
120
  flex-direction: column;
107
121
  padding: var(--rt-space-2);
108
- border-radius: var(--rt-action-bar-menu-radius);
109
- background: var(--rt-color-bg-surface);
110
- box-shadow: var(--rt-action-bar-menu-shadow);
111
- color: var(--rt-color-text-primary);
122
+ border-radius: var(--rt-action-bar-menu-radius, var(--rt-action-bar-menu-radius-default));
123
+ background: var(--rt-action-bar-menu-bg, var(--rt-color-bg-surface));
124
+ box-shadow: var(--rt-action-bar-menu-shadow, var(--rt-action-bar-menu-shadow-default));
125
+ color: var(--rt-action-bar-menu-color, var(--rt-color-text-primary));
112
126
  }
113
127
 
114
128
  // Полоса живёт на нижней кромке, и пальцу нужно место, которое занимают подписи. Решает
@@ -25,6 +25,8 @@ ref.afterClosed().subscribe((result?: ITour): void => …);
25
25
  | `width` | `string \| null` | `null` |
26
26
  | `ariaLabel` | `string \| null` | `null` |
27
27
  | `requestError` | `unknown` | `null` |
28
+ | `trapFocus` | `boolean` | `false` |
29
+ | `pending` | `boolean` | `false` |
28
30
 
29
31
  | настройка `open()` | умолчание |
30
32
  | ---------------------------------------- | ----------------------------------------- |
@@ -32,6 +34,7 @@ ref.afterClosed().subscribe((result?: ITour): void => …);
32
34
  | `position` | `'right'` |
33
35
  | `closeOnBackdropClick` / `closeOnEscape` | `true`; второе — из настроек кита |
34
36
  | `backdropClass` / `panelClass` | `rt-aside-backdrop` / `rt-aside-overlay` |
37
+ | `injector` | корневой — уничтожение хозяина закрывает |
35
38
 
36
39
  ## Главное, что нужно знать
37
40
 
@@ -54,7 +57,12 @@ ref.afterClosed().subscribe((result?: ITour): void => …);
54
57
  переопределяет своими правилами. Стережёт это `rt-aside-overlay.styles.spec.ts`.
55
58
 
56
59
  **`disableClose`** на `RtAsideRef` держит панель под кликом по подложке и под Escape — ставится
57
- самим содержимым, когда в форме есть несохранённое.
60
+ самим содержимым, когда в форме есть несохранённое. Отказанный жест — под `disableClose` или
61
+ выключенный настройкой — приходит в `closeRequests()`: `'escape'` или `'backdrop'`.
62
+
63
+ **Снятый без `close()` слой завершает `afterClosed()` значением `undefined`.** Переход по адресу
64
+ (`disposeOnNavigation`) и уничтожение хозяина больше не оставляют подписчика ждать. То же у
65
+ `RtDialogRef`.
58
66
 
59
67
  **Ошибку запроса показывает сама панель.** Вход `requestError` ставит между шапкой и содержимым
60
68
  блок `rt-aside-error-box` с кнопкой копирования ошибки; `null` и `undefined` его убирают. Своя
@@ -4,19 +4,18 @@
4
4
  .rt-aside-footer {
5
5
  --rt-aside-footer-border-width: var(--rt-border-width-thin);
6
6
 
7
- padding-top: var(--rt-aside-inset);
8
-
9
- /* Верхний разделитель не на всю ширину панели: margin отбивает футер по
10
- горизонтали на тот же инсет, что и контентная зона, поэтому
11
- border-block-start совпадает по краям с контентом. */
12
- margin: var(--rt-aside-inset);
7
+ /* Отступ и поля футера — ручки приложения; без них отступ только сверху, а поля — инсет
8
+ панели. Верхний разделитель не на всю ширину: поля отбивают футер по горизонтали на тот
9
+ же инсет, что и контентная зона, и border-block-start совпадает по краям с контентом. */
10
+ padding: var(--rt-aside-footer-inset, var(--rt-aside-inset) 0 0);
11
+ margin: var(--rt-aside-footer-margin, var(--rt-aside-inset));
13
12
  border-block-start: var(--rt-aside-footer-border-width) solid var(--rt-color-border-subtle);
14
13
 
15
14
  &__content {
16
15
  display: flex;
17
16
  flex-wrap: wrap;
18
- justify-content: space-between;
19
- gap: var(--rt-space-sm);
17
+ justify-content: var(--rt-aside-footer-justify, space-between);
18
+ gap: var(--rt-aside-footer-gap, var(--rt-space-sm));
20
19
  }
21
20
 
22
21
  &:empty {
@@ -9,7 +9,8 @@
9
9
  --rt-aside-header-gap: var(--rt-space-sm);
10
10
  --rt-aside-header-min-height: auto;
11
11
 
12
- padding: var(--rt-aside-inset);
12
+ /* Отступ шапки — ручка приложения; без неё общий инсет панели. */
13
+ padding: var(--rt-aside-header-inset, var(--rt-aside-inset));
13
14
 
14
15
  &__content {
15
16
  display: flex;
@@ -51,6 +52,9 @@
51
52
  font-size: var(--rt-aside-header-title-size);
52
53
  font-weight: var(--rt-aside-header-title-weight);
53
54
 
55
+ /* Высота строки — ручка приложения; без неё наследуется, как было. */
56
+ line-height: var(--rt-aside-header-title-leading, inherit);
57
+
54
58
  /* Ellipsis для длинного заголовка: skeleton-wrapper рендерит `{{ title }}`
55
59
  как ng-content внутри inline-flex; чтобы `text-overflow: ellipsis`
56
60
  cработал, нужен block-level контейнер с overflow: hidden над текстом. */
@@ -90,6 +94,17 @@
90
94
  }
91
95
  }
92
96
 
97
+ /* Строка под заголовком на всю ширину шапки — слот `[asideHeaderContent]`. Пустая места
98
+ не занимает. */
99
+ &__row {
100
+ min-width: 0;
101
+ margin-top: var(--rt-aside-header-gap);
102
+
103
+ &:empty {
104
+ display: none;
105
+ }
106
+ }
107
+
93
108
  /* Ряд action-иконок справа от title (отклонить / на доработку / снять с
94
109
  публикации и т.п.). Пустой при отсутствии проекции — нулевой ширины. */
95
110
  &__actions {
@@ -35,6 +35,9 @@
35
35
  }
36
36
 
37
37
  rt-aside .rt-aside {
38
+ /* Точка отсчёта для слоя ожидания. Рамка и так занимает панель целиком, поэтому прочим
39
+ потомкам она ничего не меняет. */
40
+ position: relative;
38
41
  display: flex;
39
42
  width: var(--rt-aside-width, var(--rt-aside-width-md));
40
43
 
@@ -75,6 +78,7 @@
75
78
  &__error {
76
79
  min-width: 0;
77
80
  flex-shrink: 0;
81
+ margin-block: var(--rt-aside-error-margin-block, 0);
78
82
  padding-inline: var(--rt-aside-inset);
79
83
  }
80
84
 
@@ -87,12 +91,24 @@
87
91
  min-height: 0;
88
92
  flex: 1 1 auto;
89
93
  flex-direction: column;
90
- padding: var(--rt-aside-inset);
94
+ padding: var(--rt-aside-content-inset, var(--rt-aside-inset));
91
95
  gap: var(--rt-aside-content-gap);
92
96
  overflow-y: auto;
93
97
  overscroll-behavior: contain;
94
98
  }
95
99
 
100
+ /* Слой ожидания поверх всей панели: шапка, содержимое и футер под ним не нажимаются. Тот же
101
+ вид, что у слоя дозагрузки таблицы. */
102
+ &__pending {
103
+ position: absolute;
104
+ z-index: var(--rt-z-sticky);
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ background-color: color-mix(in srgb, var(--rt-color-bg-surface) 60%, transparent);
109
+ inset: 0;
110
+ }
111
+
96
112
  &--size--sm {
97
113
  width: var(--rt-aside-width, var(--rt-aside-width-sm));
98
114
  }
@@ -10,17 +10,18 @@
10
10
  <a rtButton label="На главную" [routerLink]="'/'"></a>
11
11
  ```
12
12
 
13
- | вход | тип | умолчание |
14
- | ------------- | -------------------------------------------------------------------------- | ----------------------------- |
15
- | `label` | `string \| null` | `null` |
16
- | `icon` | `string \| null` (имя из набора `rt-icon`) | `null` |
17
- | `iconPos` | `'left' \| 'right'` | `'left'` |
18
- | `theme` | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'danger' \| 'info'` | `'primary'` |
19
- | `appearance` | `'filled' \| 'outlined' \| 'text'` | настройки кита или `'filled'` |
20
- | `size` | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'` (30 / 40 / 50 / 60 / 70 px) | настройки кита или `'md'` |
21
- | `radius` | `TRtRadius \| null` — шаг общей шкалы | настройки кита или `null` |
22
- | `loading` | `boolean` | `false` |
23
- | `loadingIcon` | `string \| null` | `null` → встроенное кольцо |
13
+ | вход | тип | умолчание |
14
+ | -------------- | -------------------------------------------------------------------------- | ---------------------------------- |
15
+ | `label` | `string \| null` | `null` |
16
+ | `icon` | `string \| null` (имя из набора `rt-icon`) | `null` |
17
+ | `iconPos` | `'left' \| 'right'` | `'left'` |
18
+ | `theme` | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'danger' \| 'info'` | `'primary'` |
19
+ | `appearance` | `'filled' \| 'outlined' \| 'text'` | настройки кита или `'filled'` |
20
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'` (30 / 40 / 50 / 60 / 70 px) | настройки кита или `'md'` |
21
+ | `radius` | `TRtRadius \| null` — шаг общей шкалы | настройки кита или `null` |
22
+ | `loading` | `boolean` | `false` |
23
+ | `loadingIcon` | `string \| null` | `null` → встроенное кольцо |
24
+ | `loadingLabel` | `'keep' \| 'hide'` | `'keep'` — кольцо рядом с подписью |
24
25
 
25
26
  Своего выхода нет — клик слушается нативным `(click)` на самом элементе.
26
27
 
@@ -91,6 +91,25 @@
91
91
  font-size: var(--rt-btn-icon-size);
92
92
  }
93
93
 
94
+ /* Лигатура шрифта Material Symbols для имени без пары — размер ей даёт `__icon` рядом.
95
+ Шрифт подключает приложение, семью можно переназначить свойством сверху. До готовности
96
+ шрифтов лигатура скрыта: иначе на её месте видно слово. */
97
+ &__glyph {
98
+ overflow: hidden;
99
+ font-family: var(--rt-icon-glyph-font, 'Material Symbols Outlined'), sans-serif;
100
+ font-feature-settings: 'liga';
101
+ font-style: normal;
102
+ font-weight: var(--rt-font-weight-regular);
103
+ letter-spacing: normal;
104
+ line-height: 1;
105
+ text-transform: none;
106
+ white-space: nowrap;
107
+
108
+ &--pending {
109
+ visibility: hidden;
110
+ }
111
+ }
112
+
94
113
  &__label {
95
114
  display: inline-flex;
96
115
  align-items: center;
@@ -264,6 +283,23 @@
264
283
  pointer-events: none;
265
284
  }
266
285
 
286
+ /* Подпись спрятана на время загрузки: содержимое гаснет прозрачностью, а не
287
+ `visibility` — так оно держит ширину и остаётся именем кнопки для скринридера.
288
+ Загрузчик встаёт поверх по центру. */
289
+ &--loading-label-hidden {
290
+ position: relative;
291
+
292
+ > :not(.rt-button__loader) {
293
+ opacity: 0;
294
+ }
295
+ }
296
+
297
+ &__loader {
298
+ position: absolute;
299
+ margin: auto;
300
+ inset: 0;
301
+ }
302
+
267
303
  /* Состояние стоит ниже всех вариантов оформления и палитры того же блока.
268
304
  Специфичность у них равная, и правила равной силы разбираются порядком в
269
305
  файле: отсюда, снизу, отключённость отменяет и заливку, и цвет подписи.
@@ -145,7 +145,7 @@
145
145
 
146
146
  /* Кнопка «назад» — круглая `mat-icon-button` первого кита, как и кнопки подвала панели. */
147
147
  .rt-aside-header__back .rt-icon-button {
148
- --rt-icon-button-size: var(--rt-data-list-settings-aside-control-size);
148
+ --rt-icon-button-size-step: var(--rt-data-list-settings-aside-control-size);
149
149
  --rt-icon-button-color: var(--rt-list-settings-icon-color);
150
150
  --rt-icon-button-radius: var(--rt-radius-full);
151
151
  }
@@ -236,7 +236,7 @@
236
236
  }
237
237
 
238
238
  .rt-data-list-settings-aside__toggle .rt-icon-button {
239
- --rt-icon-button-size: var(--rt-data-list-settings-aside-control-size);
239
+ --rt-icon-button-size-step: var(--rt-data-list-settings-aside-control-size);
240
240
  --rt-icon-button-color: var(--rt-list-settings-icon-color);
241
241
  }
242
242
  }
@@ -87,7 +87,7 @@
87
87
  --rt-icon-button-color: var(--rt-list-copy-button-color);
88
88
 
89
89
  .rt-icon-button {
90
- --rt-icon-button-size: var(--rt-list-copy-button-size);
90
+ --rt-icon-button-size-step: var(--rt-list-copy-button-size);
91
91
  --rt-icon-button-radius: var(--rt-list-copy-button-radius);
92
92
  --rt-icon-button-color-hover: var(--rt-color-text-primary);
93
93
  --rt-icon-button-color-bg-hover: var(--rt-list-copy-button-bg-hover);
@@ -39,7 +39,7 @@
39
39
  }
40
40
 
41
41
  .rt-icon-button {
42
- --rt-icon-button-size: var(--rt-list-table-button-size);
42
+ --rt-icon-button-size-step: var(--rt-list-table-button-size);
43
43
  --rt-icon-button-radius: var(--rt-list-table-button-radius);
44
44
  }
45
45
 
@@ -225,7 +225,7 @@
225
225
  }
226
226
 
227
227
  .rt-icon-button {
228
- --rt-icon-button-size: var(--rt-list-table-button-size);
228
+ --rt-icon-button-size-step: var(--rt-list-table-button-size);
229
229
  --rt-icon-button-radius: var(--rt-list-table-button-radius);
230
230
  }
231
231
 
@@ -44,6 +44,15 @@ ref.afterClosed().subscribe((ok?: boolean): void => …);
44
44
  `RtDialogRef.disableClose` держит окно и под кликом по подложке, и под Escape — ставится самим
45
45
  содержимым, когда закрывать нельзя.
46
46
 
47
+ **Фокус служба по умолчанию не трогает.** `trapFocus`, `restoreFocus` и `autoFocus` в настройке
48
+ открытия включают ловушку CDK, возврат фокуса и первый фокус (`'dialog'` — на рамку,
49
+ `'first-tabbable'` — на первый элемент под Tab). Ловушка и первый фокус ставятся после отрисовки
50
+ окна, ловушка уходит вместе с оверлеем.
51
+
52
+ **Части окна.** `rt-dialog-content` — тело с отступом и прокруткой; `rtDialogHeaderLead` — узел
53
+ перед заголовком шапки; `align` подвала — `start`, `center`, `end` (по умолчанию) или `between`.
54
+ Вид окна задают ручки `--rt-dialog-*` на корне страницы, перечень — на странице Theming.
55
+
47
56
  **Крестик в шапке ищет `RtDialogRef` необязательным инжектом.** Поэтому `rt-dialog-header` можно
48
57
  поставить и вне диалога — нажатие просто ничего не сделает, а не упадёт.
49
58
 
@@ -0,0 +1,20 @@
1
+ @layer rt-kit.components {
2
+ /* rt-dialog-content — тело модалки. ViewEncapsulation.None.
3
+ Хост адресуется по имени элемента, как у шапки и подвала: класс блока висит и на хосте, и на
4
+ узле внутри. Хост боксом не становится — тело должно быть прямым flex-ребёнком рамки, чтобы
5
+ сжиматься между шапкой и подвалом и прокручиваться само.
6
+
7
+ Свойства читаются с запасным значением на месте: окно живёт в оверлее, вне блоков
8
+ приложения, и приложение задаёт их на корне страницы. */
9
+ rt-dialog-content {
10
+ display: contents;
11
+
12
+ .rt-dialog-content {
13
+ overflow: auto;
14
+ min-height: 0;
15
+ max-height: var(--rt-dialog-content-max-height, none);
16
+ flex: 1 1 auto;
17
+ padding: var(--rt-dialog-content-padding, var(--rt-space-lg));
18
+ }
19
+ }
20
+ }
@@ -11,13 +11,29 @@
11
11
  rt-dialog-footer {
12
12
  display: contents;
13
13
 
14
+ /* Свойства читаются с запасным значением на месте — окно живёт в оверлее. Разделитель
15
+ кита лежит в частном `-default`, как у шапки. */
14
16
  .rt-dialog-footer {
17
+ --rt-dialog-footer-border-default: var(--rt-border-width-thin) solid var(--rt-color-border-subtle);
18
+
15
19
  display: flex;
16
20
  justify-content: flex-end;
17
- padding: var(--rt-space-lg);
18
- border-block-start: 1px solid var(--rt-color-border-subtle);
21
+ padding: var(--rt-dialog-footer-padding, var(--rt-space-lg));
22
+ border-block-start: var(--rt-dialog-footer-border, var(--rt-dialog-footer-border-default));
19
23
  gap: var(--rt-space-sm);
20
24
 
25
+ &--align--start {
26
+ justify-content: flex-start;
27
+ }
28
+
29
+ &--align--center {
30
+ justify-content: center;
31
+ }
32
+
33
+ &--align--between {
34
+ justify-content: space-between;
35
+ }
36
+
21
37
  &:empty {
22
38
  display: none;
23
39
  }
@@ -13,18 +13,36 @@
13
13
  rt-dialog-header {
14
14
  display: contents;
15
15
 
16
+ /* Свойства читаются с запасным значением на месте: окно живёт в оверлее, и приложение
17
+ задаёт их на корне страницы. Разделитель кита лежит в частном `-default` — проверка
18
+ токенов не пускает шаг толщины рамки запасным значением напрямую. */
16
19
  .rt-dialog-header {
20
+ --rt-dialog-header-border-default: var(--rt-border-width-thin) solid var(--rt-color-border-subtle);
21
+
17
22
  display: flex;
18
23
  align-items: center;
19
24
  justify-content: space-between;
20
- padding: var(--rt-space-lg);
21
- border-block-end: 1px solid var(--rt-color-border-subtle);
25
+ padding: var(--rt-dialog-header-padding, var(--rt-space-lg));
26
+ border-block-end: var(--rt-dialog-header-border, var(--rt-dialog-header-border-default));
22
27
  gap: var(--rt-space-sm);
23
28
 
29
+ /* Место перед заголовком: пустое ничего не занимает и не добавляет промежутка. */
30
+ &__lead {
31
+ display: inline-flex;
32
+ flex-shrink: 0;
33
+ align-items: center;
34
+
35
+ &:empty {
36
+ display: none;
37
+ }
38
+ }
39
+
24
40
  &__title {
25
41
  margin: 0;
26
42
  color: var(--rt-color-text-primary);
27
- font-size: var(--rt-text-xl);
43
+ font-size: var(--rt-dialog-title-font-size, var(--rt-text-xl));
44
+ font-weight: var(--rt-dialog-title-weight, var(--rt-font-weight-bold));
45
+ text-transform: var(--rt-dialog-title-transform, none);
28
46
  }
29
47
 
30
48
  &__close {
@@ -3,7 +3,7 @@
3
3
  @layer rt-kit.components {
4
4
  /* rt-dialog — styled frame модалки поверх CDK Overlay.
5
5
  ViewEncapsulation.None — селекторы префиксованы `.rt-dialog`.
6
- Видимость / backdrop / focus-trap обеспечивает CDK Overlay через RtDialogService. */
6
+ Видимость и подложку даёт CDK Overlay, ловушку и первый фокус — RtDialogService по флагам. */
7
7
 
8
8
  /* Хост адресуется по имени элемента, а не по классу блока: класс `.rt-dialog`
9
9
  висит и на `<rt-dialog>`, и на рамке внутри него, поэтому правила рамки
@@ -37,12 +37,18 @@
37
37
  max-height: 90dvh;
38
38
  flex-direction: column;
39
39
  padding: 0;
40
- border: none;
40
+ border: var(--rt-dialog-border, none);
41
41
  border-radius: var(--rt-dialog-radius);
42
- background: var(--rt-color-bg-surface);
42
+ background: var(--rt-dialog-bg, var(--rt-color-bg-surface));
43
43
  box-shadow: var(--rt-dialog-shadow);
44
44
  color: var(--rt-color-text-primary);
45
45
 
46
+ /* Рамку фокус берёт только по `autoFocus: 'dialog'` — как точку отсчёта для скринридера,
47
+ а не как элемент управления: кольцо вокруг всего окна читалось бы как выбор окна. */
48
+ &:focus {
49
+ outline: none;
50
+ }
51
+
46
52
  &--size--sm {
47
53
  width: var(--rt-dialog-width, var(--rt-dialog-width-sm));
48
54
  }
@@ -35,6 +35,12 @@
35
35
  - Свои кнопки у строки — `<ng-template rtDynamicSelectorRowControls let-item>`, своё название —
36
36
  `<ng-template rtDynamicSelectorRowTitle let-item>`. Корзина и ручка перетаскивания остаются китовыми.
37
37
  - Приглашение (`invitation`) встаёт вместо полосы кнопок; его кнопка открывает тот же выбор.
38
+ `listActionsShown = false` убирает сброс и очистку, оставляя кнопку добавления;
39
+ `removeShown = false` убирает корзину строк.
40
+ - Правки в своём шаблоне строки — `extraChanged`: сброс и очистка включены при прежних ключах и
41
+ сообщают `listReset` и `listCleared`, значение сброс тогда не трогает.
42
+ - Начальный запрос окна — `searchTerm`, событием поиска он не уходит. Открыто ли окно — сигнал
43
+ `popupOpen` и выход `popupOpenChange`.
38
44
 
39
45
  ## Рядом
40
46
 
@@ -26,8 +26,8 @@
26
26
 
27
27
  ## Края
28
28
 
29
- - Кнопки действий подогнаны под высоту шапки инлайновым `--rt-icon-button-size: 35px` — это
30
- осознанный выход за шкалу размеров.
29
+ - Кнопки действий идут шагом `md`, 40px. Прежний инлайновый `--rt-icon-button-size: 35px` до кнопки
30
+ не доходил и снят: после того как кнопка-значок научилась брать размер с тега, он уменьшил бы их.
31
31
  - Логотип рисуется вариантом `wordmark` высотой 15px; сами файлы даёт приложение
32
32
  (см. [`rt-logo`](../logo/CONTEXT.md)).
33
33
 
@@ -4,15 +4,19 @@
4
4
  <rt-icon name="check" size="md" color="current" [rotate]="null" />
5
5
  ```
6
6
 
7
- | вход | тип | умолчание |
8
- | -------- | ----------------------------------------------------------------------------------- | -------------- |
9
- | `name` | `IRtIcon.Name` — литеральный union из `rt-icon-names.ts` | **обязателен** |
10
- | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'` | `'md'` |
11
- | `color` | `'current' \| 'muted' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'inverse'` | `'current'` |
12
- | `rotate` | `number \| string \| null` | `null` |
7
+ | вход | тип | умолчание |
8
+ | -------- | ----------------------------------------------------------------------------------- | ----------- |
9
+ | `name` | `IRtIcon.Name \| null` — литеральный union из `rt-icon-names.ts`; побеждает `glyph` | `null` |
10
+ | `glyph` | `string \| null` — имя Material: пара кита или лигатура шрифта | `null` |
11
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| number` — число в пикселях | `'md'` |
12
+ | `color` | `'current' \| 'muted' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'inverse'` | `'current'` |
13
+ | `rotate` | `number \| string \| null` | `null` |
14
+ | `fill` | `boolean` — залитый рисунок материального набора и заливка шрифта лигатуры | `false` |
15
+ | `spin` | `boolean` — вращение, медленнее при просьбе системы о меньшем движении | `false` |
13
16
 
14
17
  Выходов нет. Размер и цвет едут инлайновым стилем host-а (`width`/`height`/`color`), не классом:
15
- `xs` 12px, `sm` 16px, `md` 20px, `lg` 24px, `xl` 32px, `2xl` 40px.
18
+ `xs` 12px, `sm` 16px, `md` 20px, `lg` 24px, `xl` 32px, `2xl` 40px, или число пикселей. Лигатура
19
+ глифа скрыта, пока шрифты страницы не готовы: её ждёт `RtIconFontService`.
16
20
 
17
21
  ## Главное, что нужно знать
18
22