@rt-tools/ui-kit-v2 0.13.1 → 0.14.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 (69) hide show
  1. package/README.md +25 -5
  2. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +45 -9
  3. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  4. package/fesm2022/rt-tools-ui-kit-v2.mjs +2265 -664
  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.14.0.tgz +0 -0
  8. package/src/lib/components/CONTEXT.md +1 -1
  9. package/src/lib/components/action-bar/rt-action-bar.component.scss +5 -0
  10. package/src/lib/components/autocomplete/rt-autocomplete.component.scss +8 -1
  11. package/src/lib/components/bottom-sheet/rt-bottom-sheet.component.scss +5 -0
  12. package/src/lib/components/button/CONTEXT.md +1 -1
  13. package/src/lib/components/button/rt-button.directive.scss +5 -7
  14. package/src/lib/components/calendar/CONTEXT.md +16 -2
  15. package/src/lib/components/calendar/rt-calendar.component.scss +81 -4
  16. package/src/lib/components/card/rt-card.component.scss +5 -0
  17. package/src/lib/components/checkbox/rt-checkbox.component.scss +5 -0
  18. package/src/lib/components/data-list/settings/rt-data-list-settings-aside.component.scss +1 -1
  19. package/src/lib/components/data-list/toolbar/rt-data-list-toolbar.component.scss +1 -1
  20. package/src/lib/components/data-table/cell/rt-data-table-cell.component.scss +1 -1
  21. package/src/lib/components/data-table/filter-cell/rt-data-table-filter-cell.component.scss +1 -1
  22. package/src/lib/components/data-table/rt-data-table.component.scss +1 -1
  23. package/src/lib/components/date-picker/CONTEXT.md +33 -14
  24. package/src/lib/components/date-picker/panel/rt-date-panel.component.scss +155 -0
  25. package/src/lib/components/date-picker/rt-date-picker.component.scss +18 -2
  26. package/src/lib/components/date-range/CONTEXT.md +53 -0
  27. package/src/lib/components/date-range/panel/rt-date-range-panel.component.scss +103 -0
  28. package/src/lib/components/date-range/rt-date-range.component.scss +120 -0
  29. package/src/lib/components/dialog/rt-dialog.component.scss +5 -0
  30. package/src/lib/components/empty-state/rt-empty-state.component.scss +5 -0
  31. package/src/lib/components/file-card/rt-file-card.component.scss +5 -0
  32. package/src/lib/components/file-drop/rt-file-drop.component.scss +5 -0
  33. package/src/lib/components/header/rt-header.component.scss +5 -0
  34. package/src/lib/components/icon-button/CONTEXT.md +1 -1
  35. package/src/lib/components/icon-button/rt-icon-button.component.scss +9 -29
  36. package/src/lib/components/input/rt-input.component.scss +7 -1
  37. package/src/lib/components/input-number/rt-input-number.component.scss +7 -1
  38. package/src/lib/components/markdown-text/rt-markdown-text.component.scss +5 -0
  39. package/src/lib/components/menu/rt-menu-item.component.scss +5 -0
  40. package/src/lib/components/message/rt-message.component.scss +5 -0
  41. package/src/lib/components/money-list/rt-money-list.component.scss +5 -0
  42. package/src/lib/components/multiselect/CONTEXT.md +12 -5
  43. package/src/lib/components/multiselect/rt-multiselect.component.scss +32 -1
  44. package/src/lib/components/note/rt-note.component.scss +5 -0
  45. package/src/lib/components/notifications-bell/rt-notifications-bell.component.scss +5 -0
  46. package/src/lib/components/pagination/rt-pagination.component.scss +6 -1
  47. package/src/lib/components/radio-button/rt-radio-button.component.scss +5 -0
  48. package/src/lib/components/section-nav/rt-section-nav.component.scss +5 -0
  49. package/src/lib/components/select/CONTEXT.md +10 -7
  50. package/src/lib/components/select/rt-select.component.scss +36 -1
  51. package/src/lib/components/skeleton/CONTEXT.md +14 -16
  52. package/src/lib/components/skeleton/rt-skeleton.component.scss +7 -1
  53. package/src/lib/components/skeleton-wrapper/CONTEXT.md +6 -6
  54. package/src/lib/components/split-button/rt-split-button.component.scss +6 -0
  55. package/src/lib/components/stepper/rt-stepper.component.scss +5 -0
  56. package/src/lib/components/table/rt-table.component.scss +12 -0
  57. package/src/lib/components/tag/CONTEXT.md +14 -15
  58. package/src/lib/components/tag/rt-tag.component.scss +6 -30
  59. package/src/lib/components/textarea/rt-textarea.component.scss +8 -1
  60. package/src/lib/components/thread-list/rt-thread-list.component.scss +5 -0
  61. package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +7 -6
  62. package/src/lib/components/toggle-switch/rt-toggle-switch.component.scss +5 -0
  63. package/src/rich-editor/lib/components/message-composer/CONTEXT.md +11 -1
  64. package/src/rich-editor/lib/components/message-composer/rt-message-composer.component.scss +78 -34
  65. package/src/styles/_mixins.scss +39 -0
  66. package/styles/tokens.css +30 -5
  67. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +11 -5
  68. package/types/rt-tools-ui-kit-v2.d.ts +394 -109
  69. package/rt-tools-ui-kit-v2-0.13.1.tgz +0 -0
@@ -1,3 +1,5 @@
1
+ @use '../../../styles/mixins' as kv;
2
+
1
3
  @layer rt-kit.components {
2
4
  /* rt-toggle-switch — переключатель в common/ui. ViewEncapsulation.None.
3
5
  Хост адресуется по имени элемента, а не по классу блока: класс `.rt-toggle-switch` висит
@@ -6,6 +8,9 @@
6
8
 
7
9
  rt-toggle-switch {
8
10
  display: inline-flex;
11
+
12
+ /* Шаг входа `radius` переназначает скругление дорожки, ручка идёт за ней. */
13
+ @include kv.radius-steps('--rt-toggle-radius', '> .rt-toggle-switch');
9
14
  }
10
15
 
11
16
  rt-toggle-switch .rt-toggle-switch {
@@ -1,6 +1,7 @@
1
1
  # `rt-message-composer`
2
2
 
3
- Поле отправки сообщения: текст, вложения, необязательное форматирование.
3
+ Поле отправки сообщения — капсула с круглыми кнопками: текст, вложения внутри капсулы,
4
+ необязательное форматирование и подсказка про Enter.
4
5
 
5
6
  ```html
6
7
  <rt-message-composer
@@ -18,6 +19,7 @@
18
19
  | `accept` | `string` | `''` |
19
20
  | `sending` / `disabled` | `boolean` | `false` |
20
21
  | `formatting` | `boolean` | `false` |
22
+ | `hint` | `boolean` | `false` |
21
23
  | `toolbar` | `TRtRichEditorToolbar` | `'full'` |
22
24
  | `minRows` / `maxRows` | `number` | 1 / 6 |
23
25
  | `droppedFiles` | `File[] \| null` | `null` |
@@ -36,6 +38,14 @@
36
38
  [`rt-file-drop`](../../../../lib/components/file-drop/CONTEXT.md) снаружи, передаются сюда входом и добавляются к
37
39
  вложениям; без `attachments` они игнорируются.
38
40
 
41
+ **Капсула высокая, когда в ней больше одной строки.** Признак — высота текста, которую меряет
42
+ `ResizeObserver`, вложенный файл или режим форматирования; модификатор `tall` переназначает
43
+ скругление на шаг 20.
44
+
45
+ **Поле держит `content-box`, внешний отступ и место под ползунок.** Автовысота CDK пишет в `height`
46
+ высоту текста и на замере обнуляет боковой `padding`, а появившийся ползунок сужал бы поле: без
47
+ этих трёх правил текст ложился бы на строку больше, чем поле вмещает.
48
+
39
49
  ## Края
40
50
 
41
51
  - После отправки форма сбрасывается целиком — и текст, и файлы.
@@ -1,74 +1,118 @@
1
1
  @layer rt-kit.components {
2
2
  .rt-message-composer {
3
- --rt-message-composer-radius: var(--rt-radius-md);
3
+ --rt-message-composer-radius: var(--rt-radius-full);
4
+ --rt-message-composer-tall-radius: var(--rt-radius-2xl);
4
5
  --rt-message-composer-border-width: var(--rt-border-width-thin);
5
- --rt-message-composer-divider-width: var(--rt-border-width-thin);
6
6
 
7
7
  display: flex;
8
8
  flex-direction: column;
9
- padding: var(--rt-space-4);
10
- border: var(--rt-message-composer-border-width) solid var(--rt-color-border-default);
11
- border-radius: var(--rt-message-composer-radius);
12
- background: var(--rt-color-bg-surface);
13
- gap: var(--rt-space-2);
9
+ gap: calc(var(--rt-space-1) * 1.5);
14
10
 
15
11
  /* Ширина приходит от хозяина, а не от содержимого. Без этой строки её задавала textarea
16
12
  без объявленной ширины: такую браузер считает от средней ширины знака первого
17
13
  доступного начертания, и величина гуляла между поднятиями витрины — 158 против 161. */
18
14
  inline-size: 100%;
19
15
 
20
- &:focus-within {
21
- border-color: var(--rt-color-border-strong);
16
+ &__capsule {
17
+ display: flex;
18
+ flex-direction: column;
19
+ padding: calc(var(--rt-space-1) * 1.5);
20
+ border: var(--rt-message-composer-border-width) solid var(--rt-input-color-border);
21
+ border-radius: var(--rt-message-composer-radius);
22
+ background: var(--rt-input-color-bg);
23
+ gap: calc(var(--rt-space-1) * 1.5);
24
+
25
+ // Фокус — как у полей кита: поверхность, рамка фокуса и кольцо.
26
+ &:focus-within {
27
+ border-color: var(--rt-input-color-border-focus);
28
+ background: var(--rt-color-bg-surface);
29
+ box-shadow: var(--rt-input-focus-shadow);
30
+ }
31
+
32
+ // Выше одной строки капсула берёт шаг скругления 20: полное скругление
33
+ // на высокой капсуле срезало бы углы текста и карточек.
34
+ &--tall {
35
+ --rt-message-composer-radius: var(--rt-message-composer-tall-radius);
36
+ }
37
+
38
+ &--disabled {
39
+ background: var(--rt-input-color-bg-disabled);
40
+ }
41
+ }
42
+
43
+ &__files {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: var(--rt-space-1);
47
+ }
48
+
49
+ &__rich {
50
+ inline-size: 100%;
51
+ }
52
+
53
+ // Кнопки прижаты к низу: растущий текст поднимает капсулу, а не их.
54
+ &__row {
55
+ display: flex;
56
+ align-items: flex-end;
57
+ gap: var(--rt-space-2);
22
58
  }
23
59
 
24
60
  &__input {
25
- padding: 0;
61
+ /* Автовысота CDK пишет в height высоту самого текста: при border-box её съели бы
62
+ отступы, и уже вторая строка уезжала бы под верхний край. */
63
+ box-sizing: content-box;
64
+ flex: 1 1 auto;
26
65
  border: 0;
27
66
  margin: 0;
28
67
  background: transparent;
29
- color: inherit;
68
+ color: var(--rt-input-color-text);
30
69
  font: inherit;
31
- font-size: var(--rt-text-sm);
70
+ font-size: var(--rt-input-font-size);
32
71
  inline-size: 100%;
33
- line-height: var(--rt-leading-snug);
72
+ line-height: var(--rt-leading-normal);
73
+
74
+ /* Отступ от скрепки — внешний: замер автовысоты CDK обнуляет боковой padding поля,
75
+ и на замере текст ложился бы в меньшее число строк, чем на экране. */
76
+ margin-inline-start: calc(var(--rt-space-1) * 1.5);
34
77
 
35
78
  /* Своего размера поле ввода хозяину не отдаёт: иначе его ширина по `cols`
36
79
  по-прежнему участвовала бы в измерении. */
37
80
  min-inline-size: 0;
38
81
  outline: 0;
82
+
83
+ /* Одна строка текста по высоте равна круглой кнопке: отступ добирает разницу. */
84
+ padding-block: calc((var(--rt-control-height-md) - 1lh) / 2);
39
85
  resize: none;
40
86
 
87
+ /* Место под ползунок держится всегда, и на замере автовысоты тоже: иначе появившийся
88
+ ползунок сужал бы поле, текст ложился бы ещё на строку, и верхняя уезжала бы. */
89
+ scrollbar-color: var(--rt-color-border-default) transparent;
90
+ scrollbar-gutter: stable;
91
+ scrollbar-width: thin;
92
+
41
93
  &::placeholder {
42
- color: var(--rt-color-text-muted);
94
+ color: var(--rt-input-color-text-placeholder);
43
95
  }
44
96
 
45
97
  &:disabled {
46
98
  cursor: not-allowed;
47
- }
48
- }
49
99
 
50
- &__files {
51
- display: flex;
52
- flex-direction: column;
53
- gap: var(--rt-space-1);
54
- }
55
-
56
- // Разделитель тянется на всю ширину бокса — компенсируем горизонтальный padding.
57
- &__divider {
58
- background: var(--rt-color-border-default);
59
- block-size: var(--rt-message-composer-divider-width);
60
- margin-inline: calc(-1 * var(--rt-space-4));
61
- }
62
-
63
- &__controls {
64
- display: flex;
65
- align-items: center;
66
- gap: var(--rt-space-2);
100
+ &::placeholder {
101
+ color: var(--rt-color-text-disabled);
102
+ }
103
+ }
67
104
  }
68
105
 
69
- // Кнопка отправки всегда у правого края, даже когда attach скрыт.
106
+ // Кнопка отправки всегда у правого края: и без скрепки, и в режиме форматирования.
70
107
  &__send {
71
108
  margin-inline-start: auto;
72
109
  }
110
+
111
+ &__hint {
112
+ margin: 0;
113
+ color: var(--rt-color-text-muted);
114
+ font-size: var(--rt-text-xs);
115
+ line-height: var(--rt-leading-snug);
116
+ }
73
117
  }
74
118
  }
@@ -19,3 +19,42 @@
19
19
  letter-spacing: var(--rt-letter-spacing-wide);
20
20
  line-height: var(--rt-leading-snug);
21
21
  }
22
+
23
+ /// Шаги скругления кита и их токены — те же шаги, что у типа `TRtRadius`. Токены названы
24
+ /// целиком, а не склеены из шага: проверка графа токенов ищет имя, а не его начало.
25
+ $radius-steps: (
26
+ none: var(--rt-radius-none),
27
+ xs: var(--rt-radius-xs),
28
+ sm: var(--rt-radius-sm),
29
+ ms: var(--rt-radius-ms),
30
+ md: var(--rt-radius-md),
31
+ lg: var(--rt-radius-lg),
32
+ xl: var(--rt-radius-xl),
33
+ 2xl: var(--rt-radius-2xl),
34
+ full: var(--rt-radius-full),
35
+ );
36
+
37
+ /// Правила шагов входа `radius` для одного компонента.
38
+ ///
39
+ /// Ставится внутрь правила хоста (`rt-card { … }`). На каждый шаг выходит правило
40
+ /// хоста с атрибутом `data-rt-radius`, которое переназначает собственное свойство
41
+ /// скругления компонента — и больше ничего: поверхность берёт углы из того же
42
+ /// свойства, и переопределение этого свойства приложением по-прежнему сильнее кита.
43
+ ///
44
+ /// $property — собственное свойство скругления, `--rt-card-radius`.
45
+ /// $surface — где это свойство объявлено, от хоста: `'> .rt-card'` для корня шаблона,
46
+ /// пусто — если на самом хосте. Только прямой ребёнок: потомок задел бы
47
+ /// вложенный компонент того же рода.
48
+ @mixin radius-steps($property, $surface: null) {
49
+ @each $step, $token in $radius-steps {
50
+ @if $surface {
51
+ &[data-rt-radius='#{$step}'] #{$surface} {
52
+ #{$property}: $token;
53
+ }
54
+ } @else {
55
+ &[data-rt-radius='#{$step}'] {
56
+ #{$property}: $token;
57
+ }
58
+ }
59
+ }
60
+ }
package/styles/tokens.css CHANGED
@@ -6905,9 +6905,6 @@ html.rt-theme-dark.rt-preset-material {
6905
6905
  .rt-button--text.rt-button--info {
6906
6906
  --rt-btn-color: var(--rt-color-action-info-on-surface);
6907
6907
  }
6908
- .rt-button--rounded {
6909
- --rt-btn-radius: 999px;
6910
- }
6911
6908
  .rt-button--sm {
6912
6909
  --rt-btn-height: var(--rt-control-height-sm);
6913
6910
  --rt-btn-padding: 0 0.875rem;
@@ -6941,8 +6938,36 @@ html.rt-theme-dark.rt-preset-material {
6941
6938
  padding: 0;
6942
6939
  gap: 0;
6943
6940
  }
6944
- .rt-button--icon-only.rt-button--rounded {
6945
- --rt-btn-radius: 50%;
6941
+ .rt-button {
6942
+ /* Шаг входа `radius` переназначает собственное свойство кнопки. Класс блока стоит на
6943
+ самом хосте, поэтому правило шага — на нём же. */
6944
+ }
6945
+ .rt-button[data-rt-radius=none] {
6946
+ --rt-btn-radius: var(--rt-radius-none);
6947
+ }
6948
+ .rt-button[data-rt-radius=xs] {
6949
+ --rt-btn-radius: var(--rt-radius-xs);
6950
+ }
6951
+ .rt-button[data-rt-radius=sm] {
6952
+ --rt-btn-radius: var(--rt-radius-sm);
6953
+ }
6954
+ .rt-button[data-rt-radius=ms] {
6955
+ --rt-btn-radius: var(--rt-radius-ms);
6956
+ }
6957
+ .rt-button[data-rt-radius=md] {
6958
+ --rt-btn-radius: var(--rt-radius-md);
6959
+ }
6960
+ .rt-button[data-rt-radius=lg] {
6961
+ --rt-btn-radius: var(--rt-radius-lg);
6962
+ }
6963
+ .rt-button[data-rt-radius=xl] {
6964
+ --rt-btn-radius: var(--rt-radius-xl);
6965
+ }
6966
+ .rt-button[data-rt-radius="2xl"] {
6967
+ --rt-btn-radius: var(--rt-radius-2xl);
6968
+ }
6969
+ .rt-button[data-rt-radius=full] {
6970
+ --rt-btn-radius: var(--rt-radius-full);
6946
6971
  }
6947
6972
  .rt-button--loading {
6948
6973
  cursor: wait;
@@ -64,9 +64,9 @@ interface IComposerFormShape {
64
64
  delta: FormControl<IQuillDelta | null>;
65
65
  }
66
66
  /**
67
- * Композер сообщения: авто-растущая textarea сверху, под разделительной линией —
68
- * ряд контролов (слева — прикрепить файл, справа — отправить). Презентационный,
69
- * без data-access: наружу торчит только `submitted` с текстом и файлами.
67
+ * Композер сообщения — капсула: слева круглая кнопка вложения, по центру авто-растущая
68
+ * textarea, справа круглая кнопка отправки; вложения стоят внутри капсулы над строкой.
69
+ * Презентационный, без data-access: наружу торчит только `submitted` с текстом и файлами.
70
70
  *
71
71
  * Отправка — `Enter` (без Shift) или клик по иконке; `Shift+Enter` — перенос
72
72
  * строки. Кнопка отправки активна, пока есть непустой текст или вложения.
@@ -76,17 +76,23 @@ declare class RtMessageComposerComponent {
76
76
  protected readonly t: Signal<TRtKitLabelMap>;
77
77
  protected readonly placeholderText: Signal<string>;
78
78
  protected readonly fileInput: Signal<ElementRef<HTMLInputElement> | undefined>;
79
+ protected readonly textInput: Signal<ElementRef<HTMLTextAreaElement> | undefined>;
79
80
  protected readonly form: FormGroup<IComposerFormShape>;
80
81
  protected readonly files: Signal<readonly File[]>;
81
82
  /** Отправка доступна: есть контент (текст/delta/файлы), композер не занят. */
82
83
  protected readonly canSend: Signal<boolean>;
84
+ /** Капсула выше одной строки: перенос текста, вложения или режим форматирования. */
85
+ protected readonly tall: Signal<boolean>;
86
+ protected readonly capsuleMods: Signal<Record<string, boolean>>;
83
87
  /** Текст-подсказка textarea. Пусто — берётся переведённое умолчание. */
84
88
  readonly placeholder: InputSignal<string>;
85
89
  /** Фильтр типов для file-input (`.pdf,.doc,...`). */
86
90
  readonly accept: InputSignal<string>;
91
+ /** Строка под капсулой про Enter и Shift + Enter. */
92
+ readonly hint: InputSignalWithTransform<boolean, BooleanInput>;
87
93
  /** Показывать кнопку вложения и список файлов. */
88
94
  readonly attachments: InputSignalWithTransform<boolean, BooleanInput>;
89
- /** Отправка в процессе — блокирует submit и показывает её недоступность. */
95
+ /** Отправка в процессе — блокирует submit, кнопка отправки крутит индикатор. */
90
96
  readonly sending: InputSignalWithTransform<boolean, BooleanInput>;
91
97
  /** Полная блокировка композера. */
92
98
  readonly disabled: InputSignalWithTransform<boolean, BooleanInput>;
@@ -113,7 +119,7 @@ declare class RtMessageComposerComponent {
113
119
  protected removeFile(index: number): void;
114
120
  protected submit(): void;
115
121
  static ɵfac: i0.ɵɵFactoryDeclaration<RtMessageComposerComponent, never>;
116
- static ɵcmp: i0.ɵɵComponentDeclaration<RtMessageComposerComponent, "rt-message-composer", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "sending": { "alias": "sending"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "formatting": { "alias": "formatting"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "minRows": { "alias": "minRows"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "droppedFiles": { "alias": "droppedFiles"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; }, never, never, true, never>;
122
+ static ɵcmp: i0.ɵɵComponentDeclaration<RtMessageComposerComponent, "rt-message-composer", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "sending": { "alias": "sending"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "formatting": { "alias": "formatting"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "minRows": { "alias": "minRows"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "droppedFiles": { "alias": "droppedFiles"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; }, never, never, true, never>;
117
123
  }
118
124
 
119
125
  /**