@rt-tools/ui-kit-v2 0.39.0 → 0.39.2

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 (88) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs +4 -4
  2. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +2 -2
  4. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +14 -0
  6. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +5 -5
  8. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +48 -45
  10. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +62 -9
  12. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +93 -12
  14. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs +2 -2
  16. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-field.mjs +2 -2
  18. package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +4 -1
  20. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs +10 -0
  22. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +76 -5
  24. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-input.mjs +2 -2
  26. package/fesm2022/rt-tools-ui-kit-v2-message.mjs +3 -3
  27. package/fesm2022/rt-tools-ui-kit-v2-message.mjs.map +1 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +4 -4
  29. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
  30. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs +37 -16
  31. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs.map +1 -1
  32. package/fesm2022/rt-tools-ui-kit-v2-table-core.mjs +101 -0
  33. package/fesm2022/rt-tools-ui-kit-v2-table-core.mjs.map +1 -0
  34. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +130 -42
  35. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  36. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +41 -4
  37. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  38. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +2 -0
  39. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
  40. package/package.json +5 -1
  41. package/src/assets/icons-material/bookmark.fill.svg +5 -0
  42. package/src/assets/icons-material/bookmark.svg +5 -0
  43. package/src/assets/icons-material/flag.fill.svg +3 -0
  44. package/src/assets/icons-material/flag.svg +5 -0
  45. package/src/lib/components/aside/footer/CONTEXT.md +27 -0
  46. package/src/lib/components/aside/footer/rt-aside-footer.component.scss +8 -3
  47. package/src/lib/components/aside/header/rt-aside-header.component.scss +11 -3
  48. package/src/lib/components/button/rt-button.directive.scss +5 -1
  49. package/src/lib/components/data-table/CONTEXT.md +8 -2
  50. package/src/lib/components/date-picker/panel/rt-date-panel.component.scss +51 -2
  51. package/src/lib/components/date-range/panel/rt-date-range-panel.component.scss +95 -2
  52. package/src/lib/components/detail-list/CONTEXT.md +3 -0
  53. package/src/lib/components/detail-list/rt-detail-row.component.scss +1 -0
  54. package/src/lib/components/field/CONTEXT.md +4 -2
  55. package/src/lib/components/field/rt-field.component.scss +14 -0
  56. package/src/lib/components/form-control/CONTEXT.md +13 -8
  57. package/src/lib/components/input/rt-input.component.scss +4 -0
  58. package/src/lib/components/input-number/CONTEXT.md +8 -0
  59. package/src/lib/components/input-number/rt-input-number.component.scss +50 -0
  60. package/src/lib/components/message/CONTEXT.md +1 -1
  61. package/src/lib/components/message/rt-message.component.scss +2 -1
  62. package/src/lib/components/multiselect/rt-multiselect.component.scss +21 -0
  63. package/src/lib/components/service-block/stories/component/test-service-block-panel.component.scss +29 -0
  64. package/src/lib/components/stat-tile/CONTEXT.md +11 -6
  65. package/src/lib/components/stat-tile/rt-stat-tile.component.scss +21 -0
  66. package/src/lib/components/stat-tile/stories/component/test-stat-tile-matrix.component.scss +15 -0
  67. package/src/lib/components/table/CONTEXT.md +23 -0
  68. package/src/lib/components/table/copy-cell/CONTEXT.md +32 -0
  69. package/src/lib/components/table/copy-cell/rt-copy-cell.component.scss +26 -0
  70. package/src/lib/components/table/rt-table.component.scss +77 -22
  71. package/src/lib/components/table/stories/component/test-table-pinned.component.scss +76 -0
  72. package/src/lib/components/tabs/CONTEXT.md +18 -16
  73. package/src/lib/components/tabs/rt-tabs.component.scss +25 -1
  74. package/src/styles/_form.scss +10 -0
  75. package/src/styles/_primitives.scss +2 -0
  76. package/src/styles/_semantic.scss +11 -1
  77. package/src/styles/_theme-dark.scss +2 -0
  78. package/styles/tokens.css +95 -9
  79. package/types/rt-tools-ui-kit-v2-core.d.ts +28 -5
  80. package/types/rt-tools-ui-kit-v2-data-table.d.ts +23 -9
  81. package/types/rt-tools-ui-kit-v2-date-picker.d.ts +14 -0
  82. package/types/rt-tools-ui-kit-v2-form-control.d.ts +2 -2
  83. package/types/rt-tools-ui-kit-v2-input-number.d.ts +30 -2
  84. package/types/rt-tools-ui-kit-v2-message.d.ts +1 -1
  85. package/types/rt-tools-ui-kit-v2-stat-tile.d.ts +29 -6
  86. package/types/rt-tools-ui-kit-v2-table-core.d.ts +76 -0
  87. package/types/rt-tools-ui-kit-v2-table.d.ts +52 -18
  88. package/types/rt-tools-ui-kit-v2-tabs.d.ts +26 -0
@@ -41,6 +41,14 @@
41
41
  /* Межбуквенный интервал подписи — ручка приложения: кит её не объявляет, без неё интервал
42
42
  наследуется от приложения, как раньше. */
43
43
  letter-spacing: var(--rt-field-label-letter-spacing, inherit);
44
+
45
+ /* Подпись своим видом кита стоит строкой в свой кегль, как в макете поля: 14 при
46
+ кегле 14. Высота строки приложения дала бы 17, и поле вышло бы выше кадра. Под
47
+ материальным набором подпись лежит и внутри поля, и там высота строки прежняя:
48
+ признак набора стоит и на предке, и на самом поле, а подпись — потомок обоих. */
49
+ &:not(:is(.rt-preset-material *, [data-preset='material'] *)) {
50
+ line-height: var(--rt-field-label-line-height);
51
+ }
44
52
  }
45
53
 
46
54
  &__required {
@@ -95,6 +103,12 @@
95
103
  line-height: var(--rt-field-messages-line-height);
96
104
  }
97
105
 
106
+ /* Своим видом кита строка подсказки — полторы высоты кегля, как в макете поля: 18 при
107
+ кегле 12. Высота строки приложения давала 14,5, и поле выходило ниже кадра. */
108
+ &:not(:is(.rt-preset-material *, [data-preset='material'] *)) {
109
+ line-height: var(--rt-leading-normal);
110
+ }
111
+
98
112
  &--reserved,
99
113
  &:has(> *) {
100
114
  padding-top: var(--rt-field-messages-padding-top);
@@ -8,14 +8,19 @@
8
8
 
9
9
  Общие входы, которые получает каждый наследник:
10
10
 
11
- | вход | тип | умолчание |
12
- | ----------- | ---------------------- | --------- |
13
- | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` |
14
- | `disabled` | `boolean` | `false` |
15
- | `controlId` | `string \| null` | `null` |
16
- | `ariaLabel` | `string \| null` | `null` |
17
- | `clearable` | `boolean` | `true` |
18
- | `bordered` | `boolean` | `true` |
11
+ | вход | тип | умолчание |
12
+ | --------------- | ---------------------- | -------------------------------------------------------- |
13
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` |
14
+ | `disabled` | `boolean` | `false` |
15
+ | `controlId` | `string \| null` | `null` |
16
+ | `ariaLabel` | `string \| null` | `null` |
17
+ | `clearable` | `boolean` | `true` |
18
+ | `clearTabbable` | `boolean` | `formControl.clearTabbable` настроек кита, иначе `false` |
19
+ | `bordered` | `boolean` | `true` |
20
+
21
+ Крестик очистки идёт по Tab, когда поле или настройки кита (`provideRtKit`, узел `formControl`)
22
+ просят об этом; вход на самом поле сильнее настроек. Шаблон наследника ставит крестику
23
+ `[tabindex]="clearTabIndex()"`, а не постоянный `-1`.
19
24
 
20
25
  ## Главное, что нужно знать
21
26
 
@@ -204,6 +204,10 @@
204
204
  letter-spacing: var(--rt-input-letter-spacing, normal);
205
205
  outline: none;
206
206
 
207
+ /* Длинное значение и подсказка, не влезшие в поле, кончаются многоточием, как в макете
208
+ поля, а не обрезаются посреди знака. */
209
+ text-overflow: ellipsis;
210
+
207
211
  &::placeholder {
208
212
  color: var(--rt-input-color-text-placeholder);
209
213
  opacity: 1;
@@ -16,6 +16,8 @@
16
16
  | `min` / `max` | `number \| null` | `null` (сторона не ограничена) |
17
17
  | `minFractionDigits` | `number` | `0` |
18
18
  | `maxFractionDigits` | `number` | `2` |
19
+ | `step` | `number` | `1` |
20
+ | `stepper` | `boolean` | `true` |
19
21
 
20
22
  Значение — `number | null`.
21
23
 
@@ -46,6 +48,12 @@
46
48
  - **Крестик обнуляет поле, а не опустошает его** (`0,00`): у числового поля ноль осмыслен.
47
49
  При нуле крестик не показывается — обнулять больше нечего.
48
50
  - Префикс спрятан от скринридера: валюту он прочитает из подписи поля.
51
+ - **Стрелки шага** стоят последними, после крестика: верхняя прибавляет `step`, нижняя вычитает.
52
+ Клавиши «вверх» и «вниз» делают то же и без стрелок. Пустое поле шагает от нуля, результат
53
+ зажимается в `min` и `max` и округляется до знаков шага. Стрелка к достигнутой границе и обе
54
+ стрелки выключенного поля гаснут. Стрелки не берут остановку таба и не забирают фокус у поля.
55
+ Обе рисуют один значок `chevron-up`, нижняя — перевёрнутым: `chevron-down` набора в 12 px
56
+ кладёт плечи неровно. В поле `sm` столбец 16×24 и значок 10 px, в `md` и `lg` — 20×32 и 12 px.
49
57
  - Под материальным набором подпись вмещающего `rt-field` ложится внутрь поля: на место подсказки
50
58
  в покое и на рамку при значении или фокусе. Признак — `fieldLabelInside` основы полей.
51
59
 
@@ -9,6 +9,7 @@
9
9
  --rt-input-number-radius: var(--rt-input-radius);
10
10
  --rt-input-number-fill-radius: var(--rt-radius-sm);
11
11
  --rt-input-number-color-border-hover: var(--rt-color-text-primary);
12
+ --rt-input-number-step-radius: var(--rt-radius-sm);
12
13
 
13
14
  /* Толщина боковой рамки: от неё под материальным набором считается отступ текста. */
14
15
  --rt-input-number-edge: var(--rt-input-border-width);
@@ -183,6 +184,55 @@
183
184
  flex-shrink: 0;
184
185
  }
185
186
 
187
+ /* Стрелки шага — столбец двух кнопок в конце поля, после крестика. */
188
+ &__stepper {
189
+ display: flex;
190
+ flex-direction: column;
191
+ flex-shrink: 0;
192
+ }
193
+
194
+ /* В поле sm стрелки мельче, как в макете: кнопки 16×12, столбец 16×24. */
195
+ &--size--sm &__step {
196
+ width: var(--rt-size-4);
197
+ height: var(--rt-size-3);
198
+ }
199
+
200
+ &__step {
201
+ display: inline-flex;
202
+ width: var(--rt-size-5);
203
+ height: var(--rt-size-4);
204
+ align-items: center;
205
+ justify-content: center;
206
+ padding: 0;
207
+ border: none;
208
+ border-radius: var(--rt-input-number-step-radius);
209
+ background: transparent;
210
+ color: var(--rt-color-text-muted);
211
+ cursor: pointer;
212
+
213
+ &:hover:not(:disabled) {
214
+ background-color: var(--rt-color-bg-hover);
215
+ color: var(--rt-color-text-primary);
216
+ }
217
+
218
+ /* Стрелка у границы и в выключенном поле гаснет: состояние ниже наведения. */
219
+ &:disabled {
220
+ color: var(--rt-color-text-disabled);
221
+ cursor: not-allowed;
222
+ }
223
+ }
224
+
225
+ /* Значок берёт цвет кнопки и не перехватывает нажатие. */
226
+ &__step-icon {
227
+ pointer-events: none;
228
+
229
+ /* Нижняя стрелка — та же верхняя, перевёрнутая: `chevron-down` набора в растре 12 px
230
+ кладёт одно плечо темнее другого, и пара читается как стрелки разного размера. */
231
+ &--flipped {
232
+ transform: rotate(180deg);
233
+ }
234
+ }
235
+
186
236
  /* Текстовый префикс (напр. «₽»): приглушён, неинтерактивен. */
187
237
  &__prefix {
188
238
  color: var(--rt-color-text-muted);
@@ -25,7 +25,7 @@
25
25
 
26
26
  ## Края
27
27
 
28
- - Иконка подставляется по палитре (`info` → `ico-info`, `success` → `check`,
28
+ - Иконка подставляется по палитре (`info` → `info-circle`, `success` → `check`,
29
29
  `warning` → `ico-warning`, `danger` → `ico-error`). У `secondary` и `neutral` иконки нет —
30
30
  они не сообщают об исходе.
31
31
  - Заданная иконка перебивает умолчание; `hideIcon` гасит любую.
@@ -48,9 +48,10 @@
48
48
  color: var(--rt-color-text-primary);
49
49
  }
50
50
 
51
+ /* Значок стоит у верхнего края текста без своего отступа, как в макете сообщения:
52
+ отступ сверху делал плашку на точку выше строки текста. */
51
53
  &__icon {
52
54
  flex-shrink: 0;
53
- margin-block-start: var(--rt-space-0-5);
54
55
  }
55
56
 
56
57
  &__body {
@@ -186,6 +186,27 @@
186
186
  flex-shrink: 0;
187
187
  }
188
188
 
189
+ /* Крестик в порядке обхода — соседняя кнопка поверх своего места в строке указателя, как у
190
+ выбора: место держит пустая ячейка размером с крестик, и чипы не заходят под него. */
191
+ &__clear-slot {
192
+ width: var(--rt-control-height-sm);
193
+ height: var(--rt-control-height-sm);
194
+ flex-shrink: 0;
195
+ }
196
+
197
+ /* Отступ считается от края хоста, а рамка стоит на кнопке внутри: её толщина входит в отступ,
198
+ иначе крестик на пиксель правее своего места. */
199
+ &__clear--outside {
200
+ position: absolute;
201
+ top: 50%;
202
+ right: calc(var(--rt-input-border-width) + var(--rt-input-padding-x) + var(--rt-size-4) + var(--rt-space-sm));
203
+ transform: translateY(-50%);
204
+ }
205
+
206
+ &--readonly &__clear--outside {
207
+ display: none;
208
+ }
209
+
189
210
  &__chevron {
190
211
  flex-shrink: 0;
191
212
  transition: transform var(--rt-multiselect-caret-transition-duration) ease;
@@ -0,0 +1,29 @@
1
+ @layer rt-kit.components {
2
+ /* Панель занимает всю высоту окна истории, как в кадре: без заданной высоты она схлопнулась бы
3
+ по содержимому, и подвал встал бы сразу под последним полем. Селектор на элемент длиннее
4
+ правила кита `rt-aside .rt-aside`: оба стоят в одном слое, и решает специфичность. */
5
+ app-service-block-panel rt-aside .rt-aside {
6
+ height: 100vh;
7
+ }
8
+
9
+ /* Раздел адреса извещений, как в одобренном макете: заголовок 16 со строкой 24, промежуток 12,
10
+ отступ 8 сверху сверх промежутка формы. Готовые части кита дают другие числа: у
11
+ `rt-aside-section` и словаря формы колонка идёт шагом 16, а строка `rt-form__title` — 1,35,
12
+ то есть 21,6. Взятые как есть, они сдвинули бы одобренный кадр, поэтому класс свой и живёт
13
+ только в истории. Раздел с шагом 12 в ките — решение о виде кита, оно за владельцем. */
14
+ .app-service-block-panel-webhook {
15
+ display: flex;
16
+ flex: 1 1 auto;
17
+ flex-direction: column;
18
+ padding-top: var(--rt-space-sm);
19
+ gap: calc(var(--rt-space-sm) + var(--rt-space-xs));
20
+
21
+ &__title {
22
+ margin: 0;
23
+ color: var(--rt-color-text-primary);
24
+ font-size: var(--rt-text-md);
25
+ font-weight: var(--rt-font-weight-semibold);
26
+ line-height: var(--rt-leading-normal);
27
+ }
28
+ }
29
+ }
@@ -12,12 +12,13 @@
12
12
  [deltaSecondary]="{ percent: 8, label: 'к прошлому году' }" />
13
13
  ```
14
14
 
15
- | вход | тип | умолчание |
16
- | --------------------------------- | --------------------------------------- | --------------- |
17
- | `label` / `value` | `string` | **обязательны** |
18
- | `secondary` | `string \| null` | `null` |
19
- | `hint` | `string \| null` | `null` |
20
- | `deltaPrimary` / `deltaSecondary` | `{ percent, label, baseline? } \| null` | `null` |
15
+ | вход | тип | умолчание |
16
+ | --------------------------------- | ---------------------------------------------- | --------------- |
17
+ | `label` / `value` | `string` | **обязательны** |
18
+ | `secondary` | `string \| null` | `null` |
19
+ | `hint` | `string \| null` | `null` |
20
+ | `deltaPrimary` / `deltaSecondary` | `{ percent, unit?, label, baseline? } \| null` | `null` |
21
+ | `growthIsWorse` | `boolean` | `false` |
21
22
 
22
23
  Выходов нет.
23
24
 
@@ -29,6 +30,10 @@
29
30
  Знак и стрелка выводятся из числа: `> 0` — «+» и стрелка вверх, `< 0` — стрелка вниз. Дробная
30
31
  часть отделяется запятой.
31
32
 
33
+ `unit: 'points'` пишет строку в процентных пунктах подписью `uiPercentagePoints` («+10 п.п.»),
34
+ без `unit` — в процентах. `growthIsWorse` меняет цвета обеих строк местами, стрелка остаётся по
35
+ знаку числа.
36
+
32
37
  **Значение базы уходит параметром подписи, а не подставляется в готовую строку.** Переводчик приложения
33
38
  интерполирует `{{value}}` в момент перевода, и к возвращённой строке подставлять уже нечего:
34
39
  `String.replace` после `translateSignal` не находил плейсхолдера, и от подписи оставалась одна
@@ -99,6 +99,27 @@
99
99
  white-space: nowrap;
100
100
  }
101
101
 
102
+ /* Рост хуже: цвета строк меняются местами, стрелки остаются по знаку числа. */
103
+ &--growth-worse {
104
+ .rt-stat-tile__delta--direction--up {
105
+ color: var(--rt-color-state-danger);
106
+ }
107
+
108
+ .rt-stat-tile__delta--direction--down {
109
+ color: var(--rt-color-state-success);
110
+ }
111
+
112
+ .rt-stat-tile__year--direction--up {
113
+ background: var(--rt-color-state-danger-bg);
114
+ color: var(--rt-color-state-danger);
115
+ }
116
+
117
+ .rt-stat-tile__year--direction--down {
118
+ background: var(--rt-color-state-success-bg);
119
+ color: var(--rt-color-state-success);
120
+ }
121
+ }
122
+
102
123
  /* Вторичная метрика прижата к низу: строки «было …» может не быть,
103
124
  и без прижатия плитки в ряду разъезжались бы по базовой линии. */
104
125
  &__secondary {
@@ -0,0 +1,15 @@
1
+ @layer rt-kit.components {
2
+ /* Ряд отчёта: плитки одной ширины в карточках, как их ставит приложение. */
3
+ .app-stat-tile-matrix {
4
+ &__report {
5
+ display: grid;
6
+ gap: var(--rt-space-4);
7
+ grid-template-columns: repeat(3, 17.5rem);
8
+ }
9
+
10
+ /* Хост карточки — сетка: так её статья тянется на высоту ряда, и карточки ряда равны. */
11
+ &__card {
12
+ display: grid;
13
+ }
14
+ }
15
+ }
@@ -22,6 +22,26 @@
22
22
  отрисовки строк, а колонка обязана попасть в реестр до неё. Ячейки колонки получают своё
23
23
  объявление тем же вызовом: без ручного присвоения CDK падает на разборе шаблона ячейки.
24
24
 
25
+ ## Закреплённая колонка
26
+
27
+ Колонку закрепляет потребитель атрибутом `sticky` или `stickyEnd` у своего `cdkColumnDef`;
28
+ своего входа у таблицы для этого нет. Закреплённая ячейка не прозрачна: она кладёт цвет своей
29
+ строки поверх подложки, поэтому колонки, уезжающие под неё при прокрутке вбок, не просвечивают.
30
+ У края закрепления тень — пока под колонкой есть прокрученное содержимое.
31
+
32
+ Свойства блока, которыми приложение меняет вид без своих правил:
33
+
34
+ | Свойство | Что задаёт | По умолчанию |
35
+ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
36
+ | `--rt-table-row-bg` | цвет строки; его же берёт закреплённая ячейка. Наведение и проблемная строка переназначают его, строке итога приложение ставит своё значение | прозрачный |
37
+ | `--rt-table-pinned-bg` | подложка закреплённой ячейки под цветом строки | поверхность, в тёмной теме — фон страницы |
38
+ | `--rt-table-pinned-shadow-color` | цвет тени у края закрепления | `--rt-color-table-pinned-shadow` |
39
+ | `--rt-table-pinned-shadow-width` | ширина тени | `12px` |
40
+
41
+ Прокрутку вбок ведёт не таблица, а её контейнер у потребителя: таблица находит ближайшего
42
+ предка, который прокручивается вбок, и по его положению ставит хосту модификаторы
43
+ `rt-table--hidden-start` и `rt-table--hidden-end`.
44
+
25
45
  ## Строка отбора
26
46
 
27
47
  Ряд отбора рисует сама таблица, по полю `filter` в `columnsConfig`, и только когда его просят
@@ -101,4 +121,7 @@
101
121
  [`rt-menu`](../menu/CONTEXT.md) в строке.
102
122
  - Отбор колонки объявляется полем `filter` в `columnsConfig`, и ряд отбора таблица рисует сама —
103
123
  см. раздел выше. Колонка без `filter` не отбирает вовсе. Строк таблица не сужает.
124
+ - Отбор и сортировку считает общее ядро таблиц `@rt-tools/ui-kit-v2/table-core`, то же, что у
125
+ `rt-data-table`. Таблица передаёт ему свой режим: пустым считается только `''`, а третье нажатие
126
+ на шапку снимает порядок.
104
127
  - Спеки логики лежат рядом: сортировка и предикат действий строки проверены отдельно.
@@ -0,0 +1,32 @@
1
+ # `rt-copy-cell`
2
+
3
+ Значение с кнопкой копирования. Кнопка рисует `ico-copy`, после нажатия на две секунды — `check`.
4
+
5
+ ```html
6
+ <rt-copy-cell [value]="row.id">{{ row.id }}</rt-copy-cell>
7
+ <rt-copy-cell framed>https://example.com/hook</rt-copy-cell>
8
+ ```
9
+
10
+ | вход | тип | умолчание |
11
+ | --------------- | ----------------------- | --------- |
12
+ | `value` | `string \| number` | `null` |
13
+ | `variant` | `IRtIconButton.Variant` | `'ghost'` |
14
+ | `revealOnHover` | `boolean` | `true` |
15
+ | `framed` | `boolean` | `false` |
16
+
17
+ ## Главное, что нужно знать
18
+
19
+ **В таблице кнопка появляется при наведении на строку.** Вне таблицы строки для наведения нет,
20
+ и `revealOnHover="false"` держит кнопку видимой всегда.
21
+
22
+ **`framed` ставит ячейку в рамку поля ввода.** Фон, рамка и радиус поля, значение кеглем поля,
23
+ отступ слева как у текста поля, кнопка видна всегда и прижата к правому краю рамки. Так адрес для
24
+ копирования стоит в форме панели подключения службы. Длинное значение в рамке переносится на
25
+ следующую строку, а не обрезается: на телефоне адрес идёт в две строки.
26
+
27
+ **Обрезанное значение показывает подсказку целиком.** Обрезка меряется в минуту наведения; в
28
+ рамке значение не обрезается.
29
+
30
+ ## Рядом
31
+
32
+ - [`rt-table`](../CONTEXT.md) — таблица, где ячейка живёт по умолчанию.
@@ -38,6 +38,32 @@
38
38
  &--static &__button {
39
39
  opacity: 1;
40
40
  }
41
+
42
+ /* framed — ячейка в рамке поля ввода на всю ширину формы: фон, рамка и радиус поля,
43
+ отступ слева как у текста поля, кнопка прижата к правому краю рамки. */
44
+ &--framed {
45
+ display: flex;
46
+ width: 100%;
47
+ box-sizing: border-box;
48
+ padding: var(--rt-space-1) var(--rt-space-1) var(--rt-space-1) var(--rt-input-padding-x);
49
+ border: var(--rt-input-border-width) solid var(--rt-input-color-border);
50
+ border-radius: var(--rt-input-radius);
51
+ background-color: var(--rt-input-color-bg);
52
+ color: var(--rt-color-text-primary);
53
+ font-size: var(--rt-text-sm);
54
+ gap: var(--rt-space-sm);
55
+ line-height: var(--rt-leading-normal);
56
+ }
57
+
58
+ /* В рамке значение переносится, а не обрезается: адрес в форме читают целиком, и на
59
+ телефоне он идёт в две строки, как в эталоне панели подключения. Без переноса строка
60
+ значения распирала форму шире панели. */
61
+ &--framed &__content {
62
+ flex: 1 1 auto;
63
+ overflow-wrap: anywhere;
64
+ text-overflow: clip;
65
+ white-space: normal;
66
+ }
41
67
  }
42
68
 
43
69
  /* Reveal при наведении/фокусе на всю строку rt-table — привычное поведение
@@ -7,20 +7,32 @@
7
7
  .rt-table {
8
8
  --rt-table-border-width: var(--rt-border-width-thin);
9
9
  --rt-table-card-radius: var(--rt-radius-md);
10
+ --rt-table-row-bg: transparent;
11
+ --rt-table-pinned-bg: var(--rt-color-table-bg);
12
+ --rt-table-pinned-shadow-color: var(--rt-color-table-pinned-shadow);
13
+ --rt-table-pinned-shadow-width: 12px;
10
14
 
11
15
  position: relative;
12
16
  display: table;
13
17
  width: 100%;
14
- background: var(--rt-color-bg-surface);
18
+ background: var(--rt-color-table-bg);
15
19
  border-collapse: collapse;
16
20
  color: var(--rt-color-text-primary);
17
21
 
22
+ /* Строка в 50 по макету вместе с отступами и нижней линией. Высота стоит на строке, а не на
23
+ ячейке: высоту ячейки браузер считает по модели размеров страницы, и под сбросом
24
+ `box-sizing: border-box` у приложения строка выходила в 37. Ширину ячеек задают приложения. */
25
+ .cdk-header-row,
26
+ .cdk-row,
27
+ &__skeleton-row {
28
+ height: 50px;
29
+ }
30
+
18
31
  .cdk-header-cell,
19
32
  .cdk-cell,
20
33
  &__filter-cell,
21
34
  &__skeleton-cell {
22
35
  position: relative;
23
- height: 50px;
24
36
  padding: var(--rt-space-2) var(--rt-space-5);
25
37
  border-bottom: var(--rt-table-border-width) solid var(--rt-color-border-subtle);
26
38
 
@@ -55,7 +67,7 @@
55
67
  .cdk-header-cell {
56
68
  /* Верхняя грань таблицы — только у шапки (низ даёт border-bottom строк). */
57
69
  border-top: var(--rt-table-border-width) solid var(--rt-color-border-subtle);
58
- background: var(--rt-color-bg-surface);
70
+ background: var(--rt-color-table-bg);
59
71
  color: var(--rt-color-text-muted);
60
72
  }
61
73
 
@@ -146,23 +158,74 @@
146
158
  }
147
159
  }
148
160
 
161
+ /* Цвет строки — свойство строки, а не правило фона: его же берёт закреплённая ячейка.
162
+ Цвета наведения и проблемной строки полупрозрачны, поэтому закреплённая ячейка кладёт
163
+ цвет строки поверх непрозрачной подложки — иначе под ней просвечивали бы колонки,
164
+ уезжающие при прокрутке вбок. Строка итога получает свой цвет тем же свойством. */
165
+ .cdk-row,
166
+ .cdk-footer-row {
167
+ background: var(--rt-table-row-bg);
168
+ }
169
+
149
170
  .cdk-row {
150
171
  &:hover {
151
- background: var(--rt-color-bg-hover);
172
+ --rt-table-row-bg: var(--rt-color-bg-hover);
152
173
  }
153
174
 
154
175
  /* Опт-ин подсветка проблемной строки (просрочка и т.п.): потребитель
155
176
  вешает класс `rt-table__row--danger` на строку. Составной селектор с
156
177
  `.cdk-row` нужен, чтобы danger-фон держался и при :hover. */
157
178
  &.rt-table__row--danger {
158
- background: var(--rt-color-state-danger-bg);
179
+ --rt-table-row-bg: var(--rt-color-state-danger-bg);
159
180
 
160
181
  &:hover {
161
- background: var(--rt-color-state-danger-bg);
182
+ --rt-table-row-bg: var(--rt-color-state-danger-bg);
162
183
  }
163
184
  }
164
185
  }
165
186
 
187
+ /* Закреплённая колонка: CDK ставит ячейке `position: sticky` и класс `cdk-table-sticky`.
188
+ Шапка уже залита поверхностью и правила не требует. */
189
+ .cdk-cell.cdk-table-sticky,
190
+ .cdk-footer-cell.cdk-table-sticky {
191
+ background: linear-gradient(var(--rt-table-row-bg), var(--rt-table-row-bg)), var(--rt-table-pinned-bg);
192
+ }
193
+
194
+ /* Тень у края: крайнюю ячейку закрепления CDK помечает классом `…-border-elem-<сторона>`.
195
+ Тень видна, пока под колонкой есть прокрученное содержимое — это говорят модификаторы
196
+ хоста `--hidden-start` и `--hidden-end`, которые таблица ставит по прокрутке. Без скрытого
197
+ края псевдоэлемента нет вовсе: невидимый, он всё равно выходил за край таблицы и давал
198
+ лишнюю прокрутку вбок. */
199
+ .cdk-table-sticky-border-elem-left,
200
+ .cdk-table-sticky-border-elem-right {
201
+ &:after {
202
+ position: absolute;
203
+ top: 0;
204
+ bottom: 0;
205
+ width: var(--rt-table-pinned-shadow-width);
206
+ pointer-events: none;
207
+ }
208
+ }
209
+
210
+ .cdk-table-sticky-border-elem-left:after {
211
+ left: 100%;
212
+ background: linear-gradient(to right, var(--rt-table-pinned-shadow-color), transparent);
213
+ }
214
+
215
+ .cdk-table-sticky-border-elem-right:after {
216
+ right: 100%;
217
+ background: linear-gradient(to left, var(--rt-table-pinned-shadow-color), transparent);
218
+ }
219
+
220
+ /* Начало и конец — логические края, а класс CDK называет физическую сторону: при письме
221
+ справа налево колонка у начала получает `…-right`. */
222
+ &--hidden-start:dir(ltr) .cdk-table-sticky-border-elem-left:after,
223
+ &--hidden-end:dir(ltr) .cdk-table-sticky-border-elem-right:after,
224
+ &--hidden-start:dir(rtl) .cdk-table-sticky-border-elem-right:after,
225
+ &--hidden-end:dir(rtl) .cdk-table-sticky-border-elem-left:after {
226
+ content: '';
227
+ }
228
+
166
229
  /* Строки-ссылки: курсор + focus-ring. Активацию (click/Enter/Space) и
167
230
  table-семантику обеспечивает директива rtTableRow на самой строке.
168
231
  Карточка узкого экрана открывает запись так же, как строка: вид у неё тот же. */
@@ -183,10 +246,15 @@
183
246
  }
184
247
 
185
248
  &--density--compact {
249
+ .cdk-header-row,
250
+ .cdk-row,
251
+ .rt-table__skeleton-row {
252
+ height: 36px;
253
+ }
254
+
186
255
  .cdk-header-cell,
187
256
  .cdk-cell,
188
257
  .rt-table__skeleton-cell {
189
- height: 36px;
190
258
  padding: var(--rt-space-xs) var(--rt-space-sm);
191
259
  }
192
260
  }
@@ -207,7 +275,7 @@
207
275
  /* Только нижняя грань — как у строк: верхнюю даёт border-bottom шапки
208
276
  (иначе двойная линия), боковые не рисуем (нет периметра). */
209
277
  border-bottom: var(--rt-table-border-width) solid var(--rt-color-border-subtle);
210
- background: var(--rt-color-bg-surface);
278
+ background: var(--rt-color-table-bg);
211
279
  color: var(--rt-color-text-muted);
212
280
  text-align: center;
213
281
  }
@@ -229,7 +297,7 @@
229
297
 
230
298
  &__overlay-backdrop {
231
299
  position: absolute;
232
- background: var(--rt-color-bg-surface);
300
+ background: var(--rt-color-table-bg);
233
301
  inset: 0;
234
302
  opacity: 0.72;
235
303
  }
@@ -349,17 +417,4 @@
349
417
  /* Шаг входа `radius` переназначает скругление карточки узкого вида; у широкого вида углов нет. */
350
418
  @include kv.radius-steps('--rt-table-card-radius');
351
419
  }
352
-
353
- /* В тёмной теме таблица сливается с фоном контента (bg-page), а не поднимается
354
- на bg-surface — иначе список выпирает более светлой плитой над страницей. */
355
- :root[data-theme='dark'] .rt-table,
356
- html.rt-theme-dark .rt-table {
357
- background: var(--rt-color-bg-page);
358
-
359
- .cdk-header-cell,
360
- .rt-table__empty,
361
- .rt-table__overlay-backdrop {
362
- background: var(--rt-color-bg-page);
363
- }
364
- }
365
420
  }