@hh.ru/magritte-ui-chat-input 1.1.19 → 1.2.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.
- package/index.css +145 -53
- package/index.d.ts +3 -0
- package/index.js +8 -1
- package/index.js.map +1 -1
- package/index.mock.d.ts +3 -0
- package/index.mock.js +5 -0
- package/index.mock.js.map +1 -1
- package/internal/ModeTransition.js +1 -1
- package/internal/TextInput.js +1 -1
- package/internal/VoiceRecord.js +1 -1
- package/internal/VoiceRecordIndicator.js +1 -1
- package/internal/flattenFragments.d.ts +6 -0
- package/internal/flattenFragments.js +20 -0
- package/internal/flattenFragments.js.map +1 -0
- package/internal/useObjectUrl.d.ts +6 -0
- package/internal/useObjectUrl.js +30 -0
- package/internal/useObjectUrl.js.map +1 -0
- package/package.json +7 -5
- package/public/ChatInput.d.ts +4 -0
- package/public/ChatInput.js +9 -1
- package/public/ChatInput.js.map +1 -1
- package/public/ChatInputChips.js +3 -5
- package/public/ChatInputChips.js.map +1 -1
- package/public/ChatInputFile.d.ts +43 -0
- package/public/ChatInputFile.js +74 -0
- package/public/ChatInputFile.js.map +1 -0
- package/public/ChatInputFiles.d.ts +6 -0
- package/public/ChatInputFiles.js +12 -0
- package/public/ChatInputFiles.js.map +1 -0
- package/public/ChatInputPreview.js +7 -2
- package/public/ChatInputPreview.js.map +1 -1
- package/public/getChatInputFileType.d.ts +5 -0
- package/public/getChatInputFileType.js +16 -0
- package/public/getChatInputFileType.js.map +1 -0
- package/styles-BHWYKmPT.js +5 -0
- package/styles-BHWYKmPT.js.map +1 -0
- package/styles-CXscNVWO.js +0 -5
- package/styles-CXscNVWO.js.map +0 -1
package/index.css
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
:root{
|
|
2
2
|
--magritte-color-background-primary-v25-1-0:#ffffff;
|
|
3
|
+
--magritte-color-background-secondary-v25-1-0:#F1F4F9;
|
|
3
4
|
--magritte-color-stroke-neutral-v25-1-0:#DCE3EB;
|
|
5
|
+
--magritte-color-stroke-phantom-v25-1-0:#DCE3EB;
|
|
4
6
|
--magritte-color-stroke-state-focused-accessible-v25-1-0:#0070ff7a;
|
|
5
7
|
--magritte-color-stroke-state-neutral-hovered-v25-1-0:#DCE3EB;
|
|
6
8
|
--magritte-color-text-primary-v25-1-0:#000000;
|
|
@@ -22,7 +24,9 @@
|
|
|
22
24
|
|
|
23
25
|
.magritte-night-theme{
|
|
24
26
|
--magritte-color-background-primary-v25-1-0:#1B1B1B;
|
|
27
|
+
--magritte-color-background-secondary-v25-1-0:#303030;
|
|
25
28
|
--magritte-color-stroke-neutral-v25-1-0:#303030;
|
|
29
|
+
--magritte-color-stroke-phantom-v25-1-0:#30303000;
|
|
26
30
|
--magritte-color-stroke-state-neutral-hovered-v25-1-0:#303030;
|
|
27
31
|
--magritte-color-text-primary-v25-1-0:#ffffff;
|
|
28
32
|
--magritte-color-text-secondary-v25-1-0:#ABABAB;
|
|
@@ -31,116 +35,127 @@
|
|
|
31
35
|
--magritte-gradient-component-chat-input-background-fade-v25-1-0:#1b1b1b00 0%, #1b1b1b 100%;
|
|
32
36
|
--magritte-shadow-level-1-color-v25-1-0:#00000029;
|
|
33
37
|
}
|
|
34
|
-
.magritte-chat-input___P69oN_1-
|
|
38
|
+
.magritte-chat-input___P69oN_1-2-0{
|
|
35
39
|
--chat-input-stroke-color:var(--magritte-color-stroke-neutral-v25-1-0);
|
|
36
40
|
--chat-input-focus-shadow:0 0 0 transparent;
|
|
37
|
-
|
|
41
|
+
position:relative;
|
|
42
|
+
isolation:isolate;
|
|
43
|
+
box-shadow:var(--chat-input-focus-shadow);
|
|
38
44
|
border-radius:24px;
|
|
39
45
|
padding:12px;
|
|
40
46
|
overflow:hidden;
|
|
41
47
|
background-color:var(--magritte-color-background-primary-v25-1-0);
|
|
42
48
|
--magritte-ui-scrollbar-offset-right:-12px;
|
|
43
49
|
}
|
|
44
|
-
.magritte-chat-input___P69oN_1-
|
|
50
|
+
.magritte-chat-input___P69oN_1-2-0::after{
|
|
51
|
+
content:'';
|
|
52
|
+
position:absolute;
|
|
53
|
+
z-index:1;
|
|
54
|
+
inset:0;
|
|
55
|
+
border-radius:inherit;
|
|
56
|
+
box-shadow:inset 0 0 0 1px var(--chat-input-stroke-color);
|
|
57
|
+
pointer-events:none;
|
|
58
|
+
}
|
|
59
|
+
.magritte-chat-input___P69oN_1-2-0.magritte-no-background___eiIY1_1-2-0{
|
|
45
60
|
background:none;
|
|
46
61
|
--chat-input-stroke-color:transparent !important;
|
|
47
62
|
}
|
|
48
|
-
.magritte-chat-input___P69oN_1-
|
|
63
|
+
.magritte-chat-input___P69oN_1-2-0:has(*:focus){
|
|
49
64
|
--chat-input-focus-shadow:var(--magritte-shadow-level-1-x-v25-1-0) var(--magritte-shadow-level-1-y-v25-1-0) var(--magritte-shadow-level-1-blur-v25-1-0) var(--magritte-shadow-level-1-spread-v25-1-0) var(--magritte-shadow-level-1-color-v25-1-0);
|
|
50
65
|
}
|
|
51
|
-
.magritte-chat-input___P69oN_1-
|
|
66
|
+
.magritte-chat-input___P69oN_1-2-0:has(.magritte-text-input-focused___TfyLu_1-2-0){
|
|
52
67
|
outline:4px solid var(--magritte-color-stroke-state-focused-accessible-v25-1-0);
|
|
53
68
|
}
|
|
54
69
|
@media (min-width: 1020px){
|
|
55
|
-
body.magritte-old-layout .magritte-chat-input___P69oN_1-
|
|
70
|
+
body.magritte-old-layout .magritte-chat-input___P69oN_1-2-0:hover{
|
|
56
71
|
--chat-input-stroke-color:var(--magritte-color-stroke-state-neutral-hovered-v25-1-0);
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
@media (min-width: 1024px){
|
|
60
|
-
body:not(.magritte-old-layout) .magritte-chat-input___P69oN_1-
|
|
75
|
+
body:not(.magritte-old-layout) .magritte-chat-input___P69oN_1-2-0:hover{
|
|
61
76
|
--chat-input-stroke-color:var(--magritte-color-stroke-state-neutral-hovered-v25-1-0);
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
|
-
.magritte-content-grid___g03sT_1-
|
|
79
|
+
.magritte-content-grid___g03sT_1-2-0{
|
|
65
80
|
display:grid;
|
|
66
81
|
grid-template-columns:auto minmax(0, 1fr) auto;
|
|
67
82
|
}
|
|
68
|
-
.magritte-content-grid___g03sT_1-
|
|
83
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-preview___baXKi_1-2-0{
|
|
69
84
|
grid-area:1 / 1 / 2 / -1;
|
|
70
85
|
}
|
|
71
|
-
.magritte-content-grid___g03sT_1-
|
|
86
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-left___7JZYp_1-2-0{
|
|
72
87
|
grid-area:3 / 1;
|
|
73
88
|
align-self:end;
|
|
74
89
|
}
|
|
75
|
-
.magritte-content-grid___g03sT_1-
|
|
90
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-central___zkguj_1-2-0{
|
|
76
91
|
grid-area:3 / 2;
|
|
77
92
|
align-self:center;
|
|
78
93
|
}
|
|
79
|
-
.magritte-content-grid___g03sT_1-
|
|
94
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-right___-tGcO_1-2-0{
|
|
80
95
|
grid-area:3 / 3;
|
|
81
96
|
align-self:end;
|
|
82
97
|
}
|
|
83
|
-
.magritte-content-grid___g03sT_1-
|
|
98
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-scrollbar-cell___--M2x_1-2-0{
|
|
84
99
|
grid-area:2 / 1 / 3 / -1;
|
|
85
100
|
position:relative;
|
|
86
101
|
pointer-events:none;
|
|
87
102
|
}
|
|
88
|
-
.magritte-content-grid___g03sT_1-
|
|
103
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-scrollbar-cell___--M2x_1-2-0 > div{
|
|
89
104
|
pointer-events:auto;
|
|
90
105
|
}
|
|
91
|
-
.magritte-content-grid___g03sT_1-
|
|
106
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-text-input___3AFO4_1-2-0{
|
|
92
107
|
grid-area:3 / 2;
|
|
93
108
|
}
|
|
94
|
-
.magritte-content-grid___g03sT_1-
|
|
95
|
-
.magritte-content-grid___g03sT_1-
|
|
109
|
+
.magritte-content-grid___g03sT_1-2-0 .magritte-text-input___3AFO4_1-2-0.magritte-layout-vertical___mVTr-_1-2-0,
|
|
110
|
+
.magritte-content-grid___g03sT_1-2-0.magritte-has-central___VRZik_1-2-0 .magritte-text-input___3AFO4_1-2-0{
|
|
96
111
|
grid-area:2 / 1 / 3 / -1;
|
|
97
112
|
}
|
|
98
|
-
.magritte-content-grid___g03sT_1-
|
|
113
|
+
.magritte-content-grid___g03sT_1-2-0.magritte-no-left-controls___7r6yy_1-2-0:not(.magritte-has-central___VRZik_1-2-0) .magritte-text-input___3AFO4_1-2-0{
|
|
99
114
|
grid-area:2 / 1 / 4 / 3;
|
|
100
115
|
}
|
|
101
|
-
.magritte-content-grid___g03sT_1-
|
|
116
|
+
.magritte-content-grid___g03sT_1-2-0.magritte-no-right-controls___HBSag_1-2-0:not(.magritte-has-central___VRZik_1-2-0) .magritte-text-input___3AFO4_1-2-0{
|
|
102
117
|
grid-area:2 / 2 / 4 / -1;
|
|
103
118
|
}
|
|
104
|
-
.magritte-content-grid___g03sT_1-
|
|
119
|
+
.magritte-content-grid___g03sT_1-2-0.magritte-no-left-controls___7r6yy_1-2-0:not(.magritte-has-central___VRZik_1-2-0){
|
|
105
120
|
grid-template-rows:auto minmax(0, 1fr) auto;
|
|
106
121
|
}
|
|
107
|
-
.magritte-right___-tGcO_1-
|
|
108
|
-
.magritte-left___7JZYp_1-
|
|
122
|
+
.magritte-right___-tGcO_1-2-0,
|
|
123
|
+
.magritte-left___7JZYp_1-2-0{
|
|
109
124
|
display:flex;
|
|
110
125
|
gap:8px;
|
|
111
126
|
}
|
|
112
|
-
.magritte-chips___gLao5_1-
|
|
127
|
+
.magritte-chips___gLao5_1-2-0{
|
|
113
128
|
display:flex;
|
|
114
129
|
flex-wrap:nowrap;
|
|
115
130
|
width:max-content;
|
|
116
131
|
gap:8px;
|
|
117
132
|
}
|
|
118
|
-
.magritte-chips-container___-bS5O_1-
|
|
133
|
+
.magritte-chips-container___-bS5O_1-2-0{
|
|
119
134
|
padding:0 12px;
|
|
120
135
|
}
|
|
121
|
-
.magritte-no-left-controls___7r6yy_1-
|
|
136
|
+
.magritte-no-left-controls___7r6yy_1-2-0 .magritte-chips-container___-bS5O_1-2-0{
|
|
122
137
|
padding-left:0;
|
|
123
138
|
}
|
|
124
|
-
.magritte-no-right-controls___HBSag_1-
|
|
139
|
+
.magritte-no-right-controls___HBSag_1-2-0 .magritte-chips-container___-bS5O_1-2-0{
|
|
125
140
|
padding-right:0;
|
|
126
141
|
}
|
|
127
|
-
.magritte-preview-block___iiPdS_1-
|
|
142
|
+
.magritte-preview-block___iiPdS_1-2-0{
|
|
128
143
|
display:flex;
|
|
129
144
|
align-items:center;
|
|
130
145
|
gap:12px;
|
|
131
146
|
padding-bottom:8px;
|
|
132
147
|
}
|
|
133
|
-
.magritte-preview-side___ymR-u_1-
|
|
148
|
+
.magritte-preview-side___ymR-u_1-2-0{
|
|
134
149
|
display:flex;
|
|
135
150
|
flex-shrink:0;
|
|
136
151
|
}
|
|
137
|
-
.magritte-preview-content___ZgyBD_1-
|
|
152
|
+
.magritte-preview-content___ZgyBD_1-2-0{
|
|
138
153
|
display:flex;
|
|
139
154
|
flex:1;
|
|
140
155
|
flex-direction:column;
|
|
141
156
|
min-width:0;
|
|
142
157
|
}
|
|
143
|
-
.magritte-preview-title___SkFeZ_1-
|
|
158
|
+
.magritte-preview-title___SkFeZ_1-2-0{
|
|
144
159
|
font-family:"hh sans";
|
|
145
160
|
font-weight:500;
|
|
146
161
|
line-height:18px;
|
|
@@ -151,7 +166,7 @@
|
|
|
151
166
|
text-decoration:none;
|
|
152
167
|
color:var(--magritte-color-text-primary-v25-1-0);
|
|
153
168
|
}
|
|
154
|
-
.magritte-preview-subtitle___58qfR_1-
|
|
169
|
+
.magritte-preview-subtitle___58qfR_1-2-0{
|
|
155
170
|
font-family:"hh sans";
|
|
156
171
|
font-weight:400;
|
|
157
172
|
line-height:20px;
|
|
@@ -165,10 +180,87 @@
|
|
|
165
180
|
white-space:nowrap;
|
|
166
181
|
text-overflow:ellipsis;
|
|
167
182
|
}
|
|
168
|
-
.magritte-
|
|
183
|
+
.magritte-files-container___zOkRK_1-2-0{
|
|
184
|
+
padding-bottom:8px;
|
|
185
|
+
}
|
|
186
|
+
.magritte-files___j2q5K_1-2-0{
|
|
187
|
+
display:flex;
|
|
188
|
+
flex-wrap:nowrap;
|
|
189
|
+
align-items:flex-start;
|
|
190
|
+
width:max-content;
|
|
191
|
+
gap:8px;
|
|
192
|
+
}
|
|
193
|
+
.magritte-file___lz9Ll_1-2-0{
|
|
194
|
+
position:relative;
|
|
195
|
+
}
|
|
196
|
+
.magritte-file-card___hn5C9_1-2-0::after,
|
|
197
|
+
.magritte-file-tile___OVlh3_1-2-0::after{
|
|
198
|
+
content:'';
|
|
199
|
+
position:absolute;
|
|
200
|
+
inset:0;
|
|
201
|
+
border:1px solid;
|
|
202
|
+
border-radius:inherit;
|
|
203
|
+
pointer-events:none;
|
|
204
|
+
}
|
|
205
|
+
.magritte-file-card___hn5C9_1-2-0{
|
|
206
|
+
position:relative;
|
|
207
|
+
box-sizing:border-box;
|
|
208
|
+
width:280px;
|
|
209
|
+
padding:8px;
|
|
210
|
+
border-radius:12px;
|
|
211
|
+
background-color:var(--magritte-color-background-primary-v25-1-0);
|
|
212
|
+
}
|
|
213
|
+
.magritte-file-card___hn5C9_1-2-0::after{
|
|
214
|
+
border-color:var(--magritte-color-stroke-neutral-v25-1-0);
|
|
215
|
+
}
|
|
216
|
+
.magritte-file-card-removable___GkxUe_1-2-0{
|
|
217
|
+
padding-right:32px;
|
|
218
|
+
}
|
|
219
|
+
.magritte-file-tile___OVlh3_1-2-0{
|
|
220
|
+
position:relative;
|
|
221
|
+
display:flex;
|
|
222
|
+
align-items:center;
|
|
223
|
+
justify-content:center;
|
|
224
|
+
width:64px;
|
|
225
|
+
height:64px;
|
|
226
|
+
overflow:hidden;
|
|
227
|
+
border-radius:12px;
|
|
228
|
+
}
|
|
229
|
+
.magritte-file-tile___OVlh3_1-2-0::after{
|
|
230
|
+
border-color:var(--magritte-color-stroke-phantom-v25-1-0);
|
|
231
|
+
}
|
|
232
|
+
.magritte-file-tile-placeholder___yxLuR_1-2-0{
|
|
233
|
+
background-color:var(--magritte-color-background-secondary-v25-1-0);
|
|
234
|
+
}
|
|
235
|
+
.magritte-file-tile-image___cZFgL_1-2-0{
|
|
236
|
+
display:block;
|
|
237
|
+
width:100%;
|
|
238
|
+
height:100%;
|
|
239
|
+
object-fit:cover;
|
|
240
|
+
}
|
|
241
|
+
.magritte-file-remove___S0WB9_1-2-0{
|
|
242
|
+
position:absolute;
|
|
243
|
+
top:4px;
|
|
244
|
+
right:4px;
|
|
245
|
+
display:flex;
|
|
246
|
+
}
|
|
247
|
+
.magritte-file-name___L03-O_1-2-0{
|
|
248
|
+
display:flex;
|
|
249
|
+
min-width:0;
|
|
250
|
+
}
|
|
251
|
+
.magritte-file-name-base___ojdp6_1-2-0{
|
|
252
|
+
overflow:hidden;
|
|
253
|
+
white-space:nowrap;
|
|
254
|
+
text-overflow:ellipsis;
|
|
255
|
+
}
|
|
256
|
+
.magritte-file-name-extension___3QZtS_1-2-0{
|
|
257
|
+
flex-shrink:0;
|
|
258
|
+
white-space:nowrap;
|
|
259
|
+
}
|
|
260
|
+
.magritte-text-input-wrapper___TPbwC_1-2-0{
|
|
169
261
|
display:contents;
|
|
170
262
|
}
|
|
171
|
-
.magritte-text-input___3AFO4_1-
|
|
263
|
+
.magritte-text-input___3AFO4_1-2-0{
|
|
172
264
|
box-sizing:content-box;
|
|
173
265
|
padding:0 12px;
|
|
174
266
|
border:none;
|
|
@@ -192,32 +284,32 @@
|
|
|
192
284
|
text-decoration:none;
|
|
193
285
|
color:var(--magritte-color-text-primary-v25-1-0);
|
|
194
286
|
}
|
|
195
|
-
.magritte-text-input___3AFO4_1-
|
|
287
|
+
.magritte-text-input___3AFO4_1-2-0::placeholder{
|
|
196
288
|
color:var(--magritte-color-text-tertiary-v25-1-0);
|
|
197
289
|
opacity:1;
|
|
198
290
|
}
|
|
199
|
-
.magritte-text-input___3AFO4_1-
|
|
200
|
-
.magritte-text-input___3AFO4_1-
|
|
291
|
+
.magritte-text-input___3AFO4_1-2-0:focus,
|
|
292
|
+
.magritte-text-input___3AFO4_1-2-0:focus-visible{
|
|
201
293
|
border:none;
|
|
202
294
|
outline:none;
|
|
203
295
|
}
|
|
204
|
-
.magritte-text-input___3AFO4_1-
|
|
205
|
-
.magritte-text-input___3AFO4_1-
|
|
296
|
+
.magritte-text-input___3AFO4_1-2-0.magritte-with-top-fade___okgqo_1-2-0,
|
|
297
|
+
.magritte-text-input___3AFO4_1-2-0.magritte-with-bottom-fade___82gr8_1-2-0{
|
|
206
298
|
-webkit-mask:var(--fade-top) top / 100% 16px no-repeat, linear-gradient(#000, #000) center / 100% calc(100% - 32px) no-repeat, var(--fade-bottom) bottom / 100% 16px no-repeat;
|
|
207
299
|
mask:var(--fade-top) top / 100% 16px no-repeat, linear-gradient(#000, #000) center / 100% calc(100% - 32px) no-repeat, var(--fade-bottom) bottom / 100% 16px no-repeat;
|
|
208
300
|
}
|
|
209
|
-
.magritte-text-input___3AFO4_1-
|
|
301
|
+
.magritte-text-input___3AFO4_1-2-0.magritte-with-top-fade___okgqo_1-2-0{
|
|
210
302
|
--fade-top:linear-gradient(180deg, var(--magritte-gradient-component-chat-input-background-fade-v25-1-0));
|
|
211
303
|
}
|
|
212
|
-
.magritte-text-input___3AFO4_1-
|
|
304
|
+
.magritte-text-input___3AFO4_1-2-0.magritte-with-bottom-fade___82gr8_1-2-0{
|
|
213
305
|
--fade-bottom:linear-gradient(0deg, var(--magritte-gradient-component-chat-input-background-fade-v25-1-0));
|
|
214
306
|
}
|
|
215
|
-
.magritte-text-input___3AFO4_1-
|
|
307
|
+
.magritte-text-input___3AFO4_1-2-0.magritte-measure___xNKc0_1-2-0{
|
|
216
308
|
height:20px !important;
|
|
217
309
|
padding:0 !important;
|
|
218
310
|
margin:0 !important;
|
|
219
311
|
}
|
|
220
|
-
.magritte-voice-record___p64PV_1-
|
|
312
|
+
.magritte-voice-record___p64PV_1-2-0{
|
|
221
313
|
display:flex;
|
|
222
314
|
align-items:center;
|
|
223
315
|
justify-content:space-between;
|
|
@@ -227,45 +319,45 @@
|
|
|
227
319
|
min-height:40px;
|
|
228
320
|
gap:8px;
|
|
229
321
|
}
|
|
230
|
-
.magritte-voice-record-left___njEt-_1-
|
|
322
|
+
.magritte-voice-record-left___njEt-_1-2-0{
|
|
231
323
|
display:flex;
|
|
232
324
|
align-items:center;
|
|
233
325
|
gap:8px;
|
|
234
326
|
min-width:0;
|
|
235
327
|
}
|
|
236
|
-
.magritte-voice-record-right___UTv-U_1-
|
|
328
|
+
.magritte-voice-record-right___UTv-U_1-2-0{
|
|
237
329
|
display:flex;
|
|
238
330
|
align-items:center;
|
|
239
331
|
gap:8px;
|
|
240
332
|
}
|
|
241
|
-
.magritte-voice-record-right___UTv-U_1-
|
|
333
|
+
.magritte-voice-record-right___UTv-U_1-2-0.magritte-voice-processing___C0xnX_1-2-0{
|
|
242
334
|
padding:8px;
|
|
243
335
|
}
|
|
244
|
-
.magritte-voice-record-indicator___V8ybb_1-
|
|
336
|
+
.magritte-voice-record-indicator___V8ybb_1-2-0{
|
|
245
337
|
display:flex;
|
|
246
338
|
flex-shrink:0;
|
|
247
339
|
align-items:center;
|
|
248
340
|
gap:2px;
|
|
249
341
|
}
|
|
250
|
-
.magritte-voice-record-indicator-bar___jgyqz_1-
|
|
342
|
+
.magritte-voice-record-indicator-bar___jgyqz_1-2-0{
|
|
251
343
|
width:2px;
|
|
252
344
|
min-height:2px;
|
|
253
345
|
max-height:2px;
|
|
254
346
|
border-radius:1000px;
|
|
255
347
|
background-color:var(--magritte-color-icon-tertiary-v25-1-0);
|
|
256
348
|
transition:max-height var(--magritte-semantic-animation-time-s-duration-v25-1-0) var(--magritte-semantic-animation-ease-base-timing-function-v25-1-0);
|
|
257
|
-
animation:magritte-voice-record-indicator-wave___4VsyE_1-
|
|
349
|
+
animation:magritte-voice-record-indicator-wave___4VsyE_1-2-0 400ms linear infinite alternate paused;
|
|
258
350
|
}
|
|
259
|
-
.magritte-voice-record-indicator-has-sound___67t5g_1-
|
|
351
|
+
.magritte-voice-record-indicator-has-sound___67t5g_1-2-0 .magritte-voice-record-indicator-bar___jgyqz_1-2-0{
|
|
260
352
|
max-height:27px;
|
|
261
353
|
animation-play-state:running;
|
|
262
354
|
}
|
|
263
355
|
@media (prefers-reduced-motion: reduce){
|
|
264
|
-
.magritte-voice-record-indicator-has-sound___67t5g_1-
|
|
356
|
+
.magritte-voice-record-indicator-has-sound___67t5g_1-2-0 .magritte-voice-record-indicator-bar___jgyqz_1-2-0{
|
|
265
357
|
animation-play-state:paused;
|
|
266
358
|
}
|
|
267
359
|
}
|
|
268
|
-
@keyframes magritte-voice-record-indicator-wave___4VsyE_1-
|
|
360
|
+
@keyframes magritte-voice-record-indicator-wave___4VsyE_1-2-0{
|
|
269
361
|
from{
|
|
270
362
|
height:calc(var(--target-height) * 0.62px);
|
|
271
363
|
}
|
|
@@ -273,12 +365,12 @@
|
|
|
273
365
|
height:calc(var(--target-height) * 1.22px);
|
|
274
366
|
}
|
|
275
367
|
}
|
|
276
|
-
.magritte-mode-container___nATVD_1-
|
|
368
|
+
.magritte-mode-container___nATVD_1-2-0{
|
|
277
369
|
position:relative;
|
|
278
370
|
display:grid;
|
|
279
371
|
align-content:end;
|
|
280
372
|
}
|
|
281
|
-
.magritte-voice-overlay___LbxAI_1-
|
|
373
|
+
.magritte-voice-overlay___LbxAI_1-2-0{
|
|
282
374
|
position:absolute;
|
|
283
375
|
right:0;
|
|
284
376
|
bottom:0;
|
package/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export { ChatInput } from '@hh.ru/magritte-ui-chat-input/public/ChatInput';
|
|
|
2
2
|
export { type ChatInputProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInput';
|
|
3
3
|
export { type ChatInputVoiceRecordConfig } from '@hh.ru/magritte-ui-chat-input/types';
|
|
4
4
|
export { type ChatInputChipsProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';
|
|
5
|
+
export { type ChatInputFileProps, type ChatInputFileState, type ChatInputFileType, } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';
|
|
6
|
+
export { getChatInputFileType } from '@hh.ru/magritte-ui-chat-input/public/getChatInputFileType';
|
|
7
|
+
export { type ChatInputFilesProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFiles';
|
|
5
8
|
export { type ChatInputPreviewProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';
|
|
6
9
|
export { type ChatInputSendButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';
|
|
7
10
|
export { type ChatInputVoiceButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';
|
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import './index.css';
|
|
2
2
|
export { ChatInput } from './public/ChatInput.js';
|
|
3
|
+
export { getChatInputFileType } from './public/getChatInputFileType.js';
|
|
3
4
|
import 'react/jsx-runtime';
|
|
4
5
|
import 'react';
|
|
5
6
|
import 'classnames';
|
|
@@ -9,7 +10,7 @@ import './internal/ChatInputContext.js';
|
|
|
9
10
|
import './internal/ModeTransition.js';
|
|
10
11
|
import 'motion/react';
|
|
11
12
|
import '@hh.ru/magritte-design-tokens/core-tokens';
|
|
12
|
-
import './styles-
|
|
13
|
+
import './styles-BHWYKmPT.js';
|
|
13
14
|
import './internal/TextInput.js';
|
|
14
15
|
import './internal/useSendOnEnter.js';
|
|
15
16
|
import '@hh.ru/magritte-common-keyboard';
|
|
@@ -28,8 +29,14 @@ import './internal/useVoiceRecordSession.js';
|
|
|
28
29
|
import './internal/voiceSlotRegistry.js';
|
|
29
30
|
import '@hh.ru/magritte-internal-slot-registry';
|
|
30
31
|
import './public/ChatInputChips.js';
|
|
32
|
+
import './internal/flattenFragments.js';
|
|
31
33
|
import '@hh.ru/magritte-ui-chips';
|
|
32
34
|
import '@hh.ru/magritte-ui-scrollable-container';
|
|
35
|
+
import './public/ChatInputFile.js';
|
|
36
|
+
import '@hh.ru/magritte-ui-cell';
|
|
37
|
+
import './internal/useObjectUrl.js';
|
|
38
|
+
import '@hh.ru/magritte-ui-link';
|
|
39
|
+
import './public/ChatInputFiles.js';
|
|
33
40
|
import './public/ChatInputPreview.js';
|
|
34
41
|
import '@hh.ru/magritte-ui-icon';
|
|
35
42
|
import './public/ChatInputSendButton.js';
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/index.mock.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { type ChatInputProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInput';
|
|
2
2
|
export { type ChatInputVoiceRecordConfig } from '@hh.ru/magritte-ui-chat-input/types';
|
|
3
3
|
export { type ChatInputChipsProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';
|
|
4
|
+
export { type ChatInputFileProps, type ChatInputFileState, type ChatInputFileType, } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';
|
|
5
|
+
export { getChatInputFileType } from '@hh.ru/magritte-ui-chat-input/public/getChatInputFileType';
|
|
6
|
+
export { type ChatInputFilesProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFiles';
|
|
4
7
|
export { type ChatInputPreviewProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';
|
|
5
8
|
export { type ChatInputSendButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';
|
|
6
9
|
export { type ChatInputVoiceButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';
|
package/index.mock.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import './index.css';
|
|
2
|
+
export { getChatInputFileType } from './public/getChatInputFileType.js';
|
|
2
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
4
|
import { forwardRef } from 'react';
|
|
4
5
|
|
|
@@ -35,6 +36,10 @@ const staticProps = {
|
|
|
35
36
|
Chips: mockComponent('Chips', undefined, {
|
|
36
37
|
withChildren: true,
|
|
37
38
|
}),
|
|
39
|
+
File: mockComponent('File'),
|
|
40
|
+
Files: mockComponent('Files', undefined, {
|
|
41
|
+
withChildren: true,
|
|
42
|
+
}),
|
|
38
43
|
Preview: mockComponent('Preview'),
|
|
39
44
|
SendButton: mockComponent('SendButton'),
|
|
40
45
|
VoiceButton: mockComponent('VoiceButton'),
|
package/index.mock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mock.js","sources":["../mock-component/lib/setupMockComponent.js","src/index.mock.ts"],"sourcesContent":["import { jsxs, jsx } from 'react/jsx-runtime';\nimport { forwardRef } from 'react';\n\nfunction enhance(mockComponent, staticProps) {\n // удаляем внутренний свойства реакта, чтобы не перезаписать ими mockComponent\n delete staticProps.type;\n delete staticProps.$$typeof;\n delete staticProps.render;\n for (const prop in staticProps) {\n mockComponent[prop] = staticProps[prop];\n }\n}\nconst MockComponent = ({ style, ...props }) => (\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line react/jsx-no-undef\njsx(\"magritte-component-mock\", { \"style-data\": style, ...props }));\nconst MockComponentRenderProp = ({ style, ...props }) => (\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line react/jsx-no-undef\njsx(\"magritte-component-mock-render-prop\", { \"style-data\": style, ...props }));\n/**\n * Возвращает mock React компонента\n */\nconst mockComponent = (componentName, staticProps = {}, { withChildren, innerDependence, WrapperComponent } = {}) => {\n const mockWrapper = forwardRef(({ children, ...props }, ref) => {\n const mock = (\n // eslint-disable-next-line react/jsx-no-undef\n jsxs(MockComponent, { ...props, _component: componentName, children: [innerDependence ? innerDependence(props, ref) : null, withChildren ? children : null] }));\n return WrapperComponent ? jsx(WrapperComponent, { ...props, children: mock }) : mock;\n });\n staticProps && enhance(mockWrapper, staticProps);\n mockWrapper.displayName = 'magritte-ref';\n return mockWrapper;\n};\n/**\n * Возвращает mock React компонента, который рендерит переданный в него пропс render\n *\n * @param {String} componentName наименование компонента\n * @param {Object} [staticProps] объект со свойствами, которыми необходимо усилить mock\n * @param {Object} [options] параметры мока\n * @param {boolean} [options.withChildren] флаг отвечает за рендеринг children компонента\n * @param {React.Component} [options.innerDependence] Реакт компонент, который рендерится внутри мока.\n * Необходим, когда mock компоненту требуется иметь\n * дополнительные элементы\n */\nconst mockComponentRenderProp = (componentName, staticProps, { withChildren, innerDependence, renderArguments } = { renderArguments: [] }) => {\n const mockWrapper = ({ render, children, ...props }) => (jsxs(MockComponentRenderProp, { ...props, _component: componentName, children: [innerDependence ? innerDependence(props) : null, withChildren ? children : null, render?.(...(renderArguments || []))] }));\n staticProps && enhance(mockWrapper, staticProps);\n mockWrapper.displayName = 'magritte-component-mock-render-prop';\n return mockWrapper;\n};\n\nexport { mockComponent, mockComponentRenderProp };\n//# sourceMappingURL=setupMockComponent.js.map\n","import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport { type ChatInputProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInput';\nexport { type ChatInputVoiceRecordConfig } from '@hh.ru/magritte-ui-chat-input/types';\nexport { type ChatInputChipsProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';\nexport { type ChatInputPreviewProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';\nexport { type ChatInputSendButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';\nexport { type ChatInputVoiceButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';\n\nconst staticProps = {\n Chips: mockComponent('Chips', undefined, {\n withChildren: true,\n }),\n Preview: mockComponent('Preview'),\n SendButton: mockComponent('SendButton'),\n VoiceButton: mockComponent('VoiceButton'),\n};\n\nexport const ChatInput = mockComponent('ChatInput', staticProps, {\n withChildren: true,\n});\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mock.js","sources":["../mock-component/lib/setupMockComponent.js","src/index.mock.ts"],"sourcesContent":["import { jsxs, jsx } from 'react/jsx-runtime';\nimport { forwardRef } from 'react';\n\nfunction enhance(mockComponent, staticProps) {\n // удаляем внутренний свойства реакта, чтобы не перезаписать ими mockComponent\n delete staticProps.type;\n delete staticProps.$$typeof;\n delete staticProps.render;\n for (const prop in staticProps) {\n mockComponent[prop] = staticProps[prop];\n }\n}\nconst MockComponent = ({ style, ...props }) => (\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line react/jsx-no-undef\njsx(\"magritte-component-mock\", { \"style-data\": style, ...props }));\nconst MockComponentRenderProp = ({ style, ...props }) => (\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line react/jsx-no-undef\njsx(\"magritte-component-mock-render-prop\", { \"style-data\": style, ...props }));\n/**\n * Возвращает mock React компонента\n */\nconst mockComponent = (componentName, staticProps = {}, { withChildren, innerDependence, WrapperComponent } = {}) => {\n const mockWrapper = forwardRef(({ children, ...props }, ref) => {\n const mock = (\n // eslint-disable-next-line react/jsx-no-undef\n jsxs(MockComponent, { ...props, _component: componentName, children: [innerDependence ? innerDependence(props, ref) : null, withChildren ? children : null] }));\n return WrapperComponent ? jsx(WrapperComponent, { ...props, children: mock }) : mock;\n });\n staticProps && enhance(mockWrapper, staticProps);\n mockWrapper.displayName = 'magritte-ref';\n return mockWrapper;\n};\n/**\n * Возвращает mock React компонента, который рендерит переданный в него пропс render\n *\n * @param {String} componentName наименование компонента\n * @param {Object} [staticProps] объект со свойствами, которыми необходимо усилить mock\n * @param {Object} [options] параметры мока\n * @param {boolean} [options.withChildren] флаг отвечает за рендеринг children компонента\n * @param {React.Component} [options.innerDependence] Реакт компонент, который рендерится внутри мока.\n * Необходим, когда mock компоненту требуется иметь\n * дополнительные элементы\n */\nconst mockComponentRenderProp = (componentName, staticProps, { withChildren, innerDependence, renderArguments } = { renderArguments: [] }) => {\n const mockWrapper = ({ render, children, ...props }) => (jsxs(MockComponentRenderProp, { ...props, _component: componentName, children: [innerDependence ? innerDependence(props) : null, withChildren ? children : null, render?.(...(renderArguments || []))] }));\n staticProps && enhance(mockWrapper, staticProps);\n mockWrapper.displayName = 'magritte-component-mock-render-prop';\n return mockWrapper;\n};\n\nexport { mockComponent, mockComponentRenderProp };\n//# sourceMappingURL=setupMockComponent.js.map\n","import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport { type ChatInputProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInput';\nexport { type ChatInputVoiceRecordConfig } from '@hh.ru/magritte-ui-chat-input/types';\nexport { type ChatInputChipsProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';\nexport {\n type ChatInputFileProps,\n type ChatInputFileState,\n type ChatInputFileType,\n} from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';\nexport { getChatInputFileType } from '@hh.ru/magritte-ui-chat-input/public/getChatInputFileType';\nexport { type ChatInputFilesProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFiles';\nexport { type ChatInputPreviewProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';\nexport { type ChatInputSendButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';\nexport { type ChatInputVoiceButtonProps } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';\n\nconst staticProps = {\n Chips: mockComponent('Chips', undefined, {\n withChildren: true,\n }),\n File: mockComponent('File'),\n Files: mockComponent('Files', undefined, {\n withChildren: true,\n }),\n Preview: mockComponent('Preview'),\n SendButton: mockComponent('SendButton'),\n VoiceButton: mockComponent('VoiceButton'),\n};\n\nexport const ChatInput = mockComponent('ChatInput', staticProps, {\n withChildren: true,\n});\n"],"names":[],"mappings":";;;;AAGA,SAAS,OAAO,CAAC,aAAa,EAAE,WAAW,EAAE;AAC7C;AACA,IAAI,OAAO,WAAW,CAAC,IAAI,CAAC;AAC5B,IAAI,OAAO,WAAW,CAAC,QAAQ,CAAC;AAChC,IAAI,OAAO,WAAW,CAAC,MAAM,CAAC;AAC9B,IAAI,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE;AACpC,QAAQ,aAAa,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;AAChD,KAAK;AACL,CAAC;AACD,MAAM,aAAa,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE;AAC1C;AACA;AACA;AACA,GAAG,CAAC,yBAAyB,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAMnE;AACA;AACA;AACA,MAAM,aAAa,GAAG,CAAC,aAAa,EAAE,WAAW,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,EAAE,KAAK;AACrH,IAAI,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK;AACpE,QAAQ,MAAM,IAAI;AAClB;AACA,QAAQ,IAAI,CAAC,aAAa,EAAE,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,eAAe,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACxK,QAAQ,OAAO,gBAAgB,GAAG,GAAG,CAAC,gBAAgB,EAAE,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;AAC7F,KAAK,CAAC,CAAC;AACP,IAAI,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AACrD,IAAI,WAAW,CAAC,WAAW,GAAG,cAAc,CAAC;AAC7C,IAAI,OAAO,WAAW,CAAC;AACvB,CAAC;;ACnBD,MAAM,WAAW,GAAG;AAChB,IAAA,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE;AACrC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC;AAC3B,IAAA,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE;AACrC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC;AACjC,IAAA,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC;AACvC,IAAA,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC;CAC5C,CAAC;MAEW,SAAS,GAAG,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE;AAC7D,IAAA,YAAY,EAAE,IAAI;AACrB,CAAA;;;;"}
|
|
@@ -2,7 +2,7 @@ import './../index.css';
|
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useReducedMotion, motion } from 'motion/react';
|
|
4
4
|
import CoreTokens from '@hh.ru/magritte-design-tokens/core-tokens';
|
|
5
|
-
import { s as styles } from '../styles-
|
|
5
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
6
6
|
|
|
7
7
|
const EASE_BASE = [
|
|
8
8
|
CoreTokens['magritte-semantic-animation-ease-base'].x1,
|
package/internal/TextInput.js
CHANGED
|
@@ -5,7 +5,7 @@ import classNames from 'classnames';
|
|
|
5
5
|
import { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';
|
|
6
6
|
import { useSendOnEnter } from './useSendOnEnter.js';
|
|
7
7
|
import { useScrollbar, Scrollbar } from '@hh.ru/magritte-ui-scrollbar';
|
|
8
|
-
import { s as styles } from '../styles-
|
|
8
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
9
9
|
import '@hh.ru/magritte-common-keyboard';
|
|
10
10
|
|
|
11
11
|
const MIN_HEIGHT = 20;
|
package/internal/VoiceRecord.js
CHANGED
|
@@ -9,7 +9,7 @@ import { FOCUS_PRIORITY } from './focusGroup.js';
|
|
|
9
9
|
import { CrossOutlinedSize24, CheckOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';
|
|
10
10
|
import { Loader } from '@hh.ru/magritte-ui-loader';
|
|
11
11
|
import { Text } from '@hh.ru/magritte-ui-typography';
|
|
12
|
-
import { s as styles } from '../styles-
|
|
12
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
13
13
|
import './useHasSound.js';
|
|
14
14
|
|
|
15
15
|
const formatDuration = (totalSeconds) => {
|
|
@@ -2,7 +2,7 @@ import './../index.css';
|
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { useHasSound } from './useHasSound.js';
|
|
5
|
-
import { s as styles } from '../styles-
|
|
5
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
6
6
|
import 'react';
|
|
7
7
|
|
|
8
8
|
const TARGET_HEIGHT = [2, 11, 22, 22, 22, 11, 22, 11, 6, 2];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/** Раскрывает фрагменты в плоский список детей. Children.toArray сохраняет ключи детей —
|
|
3
|
+
* их можно перенести на обёртку, чтобы удаление элемента из середины не сдвигало стейт соседей.
|
|
4
|
+
* Внутренний Children.toArray нумерует детей фрагмента заново (.0, .1), поэтому к их ключам
|
|
5
|
+
* добавляется ключ фрагмента — иначе они совпадут с ключами соседей фрагмента */
|
|
6
|
+
export declare const flattenFragments: (children: ReactNode, keyPrefix?: string) => ReactNode[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './../index.css';
|
|
2
|
+
import { Children, isValidElement, Fragment, cloneElement } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Раскрывает фрагменты в плоский список детей. Children.toArray сохраняет ключи детей —
|
|
5
|
+
* их можно перенести на обёртку, чтобы удаление элемента из середины не сдвигало стейт соседей.
|
|
6
|
+
* Внутренний Children.toArray нумерует детей фрагмента заново (.0, .1), поэтому к их ключам
|
|
7
|
+
* добавляется ключ фрагмента — иначе они совпадут с ключами соседей фрагмента */
|
|
8
|
+
const flattenFragments = (children, keyPrefix = '') => Children.toArray(children).flatMap((child) => {
|
|
9
|
+
if (!isValidElement(child)) {
|
|
10
|
+
return child;
|
|
11
|
+
}
|
|
12
|
+
const key = `${keyPrefix}${child.key}`;
|
|
13
|
+
if (child.type === Fragment) {
|
|
14
|
+
return flattenFragments(child.props.children, key);
|
|
15
|
+
}
|
|
16
|
+
return keyPrefix ? cloneElement(child, { key }) : child;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export { flattenFragments };
|
|
20
|
+
//# sourceMappingURL=flattenFragments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flattenFragments.js","sources":["src/internal/flattenFragments.ts"],"sourcesContent":["import { Children, cloneElement, Fragment, isValidElement, type PropsWithChildren, type ReactNode } from 'react';\n\n/** Раскрывает фрагменты в плоский список детей. Children.toArray сохраняет ключи детей —\n * их можно перенести на обёртку, чтобы удаление элемента из середины не сдвигало стейт соседей.\n * Внутренний Children.toArray нумерует детей фрагмента заново (.0, .1), поэтому к их ключам\n * добавляется ключ фрагмента — иначе они совпадут с ключами соседей фрагмента */\nexport const flattenFragments = (children: ReactNode, keyPrefix = ''): ReactNode[] =>\n Children.toArray(children).flatMap((child) => {\n if (!isValidElement(child)) {\n return child;\n }\n const key = `${keyPrefix}${child.key}`;\n if (child.type === Fragment) {\n return flattenFragments((child.props as PropsWithChildren).children, key);\n }\n return keyPrefix ? cloneElement(child, { key }) : child;\n });\n"],"names":[],"mappings":";;AAEA;;;AAGiF;AACpE,MAAA,gBAAgB,GAAG,CAAC,QAAmB,EAAE,SAAS,GAAG,EAAE,KAChE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,KAAI;AACzC,IAAA,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE;AACxB,QAAA,OAAO,KAAK,CAAC;KAChB;IACD,MAAM,GAAG,GAAG,CAAG,EAAA,SAAS,GAAG,KAAK,CAAC,GAAG,CAAA,CAAE,CAAC;AACvC,IAAA,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;QACzB,OAAO,gBAAgB,CAAE,KAAK,CAAC,KAA2B,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;KAC7E;AACD,IAAA,OAAO,SAAS,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;AAC5D,CAAC;;;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Url для отображения картинки: строку возвращает как есть, для Blob/File создаёт локальный object URL
|
|
3
|
+
* и отзывает его при смене источника и размонтировании. Blob с известным не-image типом пропускаем.
|
|
4
|
+
* URL создаётся в эффекте (не в рендере), поэтому StrictMode и SSR его не теряют и не плодят
|
|
5
|
+
*/
|
|
6
|
+
export declare const useObjectUrl: (source: string | Blob | undefined) => string | undefined;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import './../index.css';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
const isImageBlob = (blob) => !blob.type || blob.type.startsWith('image/');
|
|
5
|
+
/**
|
|
6
|
+
* Url для отображения картинки: строку возвращает как есть, для Blob/File создаёт локальный object URL
|
|
7
|
+
* и отзывает его при смене источника и размонтировании. Blob с известным не-image типом пропускаем.
|
|
8
|
+
* URL создаётся в эффекте (не в рендере), поэтому StrictMode и SSR его не теряют и не плодят
|
|
9
|
+
*/
|
|
10
|
+
const useObjectUrl = (source) => {
|
|
11
|
+
const blob = source instanceof Blob && isImageBlob(source) ? source : undefined;
|
|
12
|
+
const [objectUrl, setObjectUrl] = useState();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!blob) {
|
|
15
|
+
setObjectUrl(undefined);
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const url = URL.createObjectURL(blob);
|
|
19
|
+
setObjectUrl({ blob, url });
|
|
20
|
+
return () => URL.revokeObjectURL(url);
|
|
21
|
+
}, [blob]);
|
|
22
|
+
if (typeof source === 'string') {
|
|
23
|
+
return source;
|
|
24
|
+
}
|
|
25
|
+
// url от предыдущего Blob уже отозван — до эффекта для нового ничего не отдаём
|
|
26
|
+
return objectUrl && objectUrl.blob === blob ? objectUrl.url : undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { useObjectUrl };
|
|
30
|
+
//# sourceMappingURL=useObjectUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useObjectUrl.js","sources":["src/internal/useObjectUrl.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nconst isImageBlob = (blob: Blob): boolean => !blob.type || blob.type.startsWith('image/');\n\n/**\n * Url для отображения картинки: строку возвращает как есть, для Blob/File создаёт локальный object URL\n * и отзывает его при смене источника и размонтировании. Blob с известным не-image типом пропускаем.\n * URL создаётся в эффекте (не в рендере), поэтому StrictMode и SSR его не теряют и не плодят\n */\nexport const useObjectUrl = (source: string | Blob | undefined): string | undefined => {\n const blob = source instanceof Blob && isImageBlob(source) ? source : undefined;\n const [objectUrl, setObjectUrl] = useState<{ blob: Blob; url: string }>();\n\n useEffect(() => {\n if (!blob) {\n setObjectUrl(undefined);\n return undefined;\n }\n const url = URL.createObjectURL(blob);\n setObjectUrl({ blob, url });\n return () => URL.revokeObjectURL(url);\n }, [blob]);\n\n if (typeof source === 'string') {\n return source;\n }\n // url от предыдущего Blob уже отозван — до эффекта для нового ничего не отдаём\n return objectUrl && objectUrl.blob === blob ? objectUrl.url : undefined;\n};\n"],"names":[],"mappings":";;AAEA,MAAM,WAAW,GAAG,CAAC,IAAU,KAAc,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAE1F;;;;AAIG;AACU,MAAA,YAAY,GAAG,CAAC,MAAiC,KAAwB;AAClF,IAAA,MAAM,IAAI,GAAG,MAAM,YAAY,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAChF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,EAA+B,CAAC;IAE1E,SAAS,CAAC,MAAK;QACX,IAAI,CAAC,IAAI,EAAE;YACP,YAAY,CAAC,SAAS,CAAC,CAAC;AACxB,YAAA,OAAO,SAAS,CAAC;SACpB;QACD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AACtC,QAAA,YAAY,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5B,OAAO,MAAM,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAC1C,KAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AAEX,IAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5B,QAAA,OAAO,MAAM,CAAC;KACjB;;AAED,IAAA,OAAO,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC;AAC5E;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hh.ru/magritte-ui-chat-input",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"sideEffects": [
|
|
@@ -30,15 +30,17 @@
|
|
|
30
30
|
"@hh.ru/magritte-common-keyboard": "4.3.5",
|
|
31
31
|
"@hh.ru/magritte-common-use-disabled": "1.0.15",
|
|
32
32
|
"@hh.ru/magritte-common-use-multiple-refs": "1.1.11",
|
|
33
|
-
"@hh.ru/magritte-common-use-translation": "3.
|
|
33
|
+
"@hh.ru/magritte-common-use-translation": "3.6.0",
|
|
34
34
|
"@hh.ru/magritte-design-tokens": "25.1.0",
|
|
35
35
|
"@hh.ru/magritte-internal-slot-registry": "1.1.0",
|
|
36
|
-
"@hh.ru/magritte-ui-
|
|
36
|
+
"@hh.ru/magritte-ui-cell": "7.3.0",
|
|
37
|
+
"@hh.ru/magritte-ui-chips": "7.0.44",
|
|
37
38
|
"@hh.ru/magritte-ui-icon": "15.1.2",
|
|
39
|
+
"@hh.ru/magritte-ui-link": "7.2.3",
|
|
38
40
|
"@hh.ru/magritte-ui-loader": "4.1.3",
|
|
39
|
-
"@hh.ru/magritte-ui-scrollable-container": "6.
|
|
41
|
+
"@hh.ru/magritte-ui-scrollable-container": "6.5.0",
|
|
40
42
|
"@hh.ru/magritte-ui-scrollbar": "1.0.36",
|
|
41
43
|
"@hh.ru/magritte-ui-typography": "5.3.13"
|
|
42
44
|
},
|
|
43
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "4420819c71c2d263ef47b3208c47942e9f0a1d30"
|
|
44
46
|
}
|
package/public/ChatInput.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ChangeEventHandler, type ForwardedRef, type ForwardRefExoticComponent, type ReactNode, type RefAttributes, type TextareaHTMLAttributes } from 'react';
|
|
2
2
|
import { ChatInputChips } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';
|
|
3
|
+
import { ChatInputFile } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';
|
|
4
|
+
import { ChatInputFiles } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFiles';
|
|
3
5
|
import { ChatInputPreview } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';
|
|
4
6
|
import { ChatInputSendButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';
|
|
5
7
|
import { ChatInputVoiceButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';
|
|
@@ -39,6 +41,8 @@ interface ChatInputOwnProps {
|
|
|
39
41
|
export type ChatInputProps = ChatInputOwnProps & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof ChatInputOwnProps | 'defaultValue'>;
|
|
40
42
|
interface ChatInputComponents {
|
|
41
43
|
Chips: typeof ChatInputChips;
|
|
44
|
+
File: typeof ChatInputFile;
|
|
45
|
+
Files: typeof ChatInputFiles;
|
|
42
46
|
Preview: typeof ChatInputPreview;
|
|
43
47
|
SendButton: typeof ChatInputSendButton;
|
|
44
48
|
VoiceButton: typeof ChatInputVoiceButton;
|
package/public/ChatInput.js
CHANGED
|
@@ -13,11 +13,13 @@ import { useRovingFocusGroup } from '../internal/useRovingFocusGroup.js';
|
|
|
13
13
|
import { useVoiceRecordSession } from '../internal/useVoiceRecordSession.js';
|
|
14
14
|
import { ChatInputVoiceSlotProvider, useVoiceConfig } from '../internal/voiceSlotRegistry.js';
|
|
15
15
|
import { ChatInputChips } from './ChatInputChips.js';
|
|
16
|
+
import { ChatInputFile } from './ChatInputFile.js';
|
|
17
|
+
import { ChatInputFiles } from './ChatInputFiles.js';
|
|
16
18
|
import { ChatInputPreview } from './ChatInputPreview.js';
|
|
17
19
|
import { ChatInputSendButton } from './ChatInputSendButton.js';
|
|
18
20
|
import { ChatInputVoiceButton } from './ChatInputVoiceButton.js';
|
|
19
21
|
import { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';
|
|
20
|
-
import { s as styles } from '../styles-
|
|
22
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
21
23
|
import 'motion/react';
|
|
22
24
|
import '@hh.ru/magritte-design-tokens/core-tokens';
|
|
23
25
|
import '../internal/useSendOnEnter.js';
|
|
@@ -31,8 +33,12 @@ import '@hh.ru/magritte-ui-icon/icon';
|
|
|
31
33
|
import '@hh.ru/magritte-ui-loader';
|
|
32
34
|
import '@hh.ru/magritte-ui-typography';
|
|
33
35
|
import '@hh.ru/magritte-internal-slot-registry';
|
|
36
|
+
import '../internal/flattenFragments.js';
|
|
34
37
|
import '@hh.ru/magritte-ui-chips';
|
|
35
38
|
import '@hh.ru/magritte-ui-scrollable-container';
|
|
39
|
+
import '@hh.ru/magritte-ui-cell';
|
|
40
|
+
import '../internal/useObjectUrl.js';
|
|
41
|
+
import '@hh.ru/magritte-ui-link';
|
|
36
42
|
import '../internal/ChatInputSlotButton.js';
|
|
37
43
|
|
|
38
44
|
const DEFAULT_ICON_PROPS = {
|
|
@@ -114,6 +120,8 @@ const ChatInputComponent = (props, ref) => (jsx(ChatInputVoiceSlotProvider, { ch
|
|
|
114
120
|
const ChatInput = forwardRef(ChatInputComponent);
|
|
115
121
|
ChatInput.displayName = 'ChatInput';
|
|
116
122
|
ChatInput.Chips = ChatInputChips;
|
|
123
|
+
ChatInput.File = ChatInputFile;
|
|
124
|
+
ChatInput.Files = ChatInputFiles;
|
|
117
125
|
ChatInput.Preview = ChatInputPreview;
|
|
118
126
|
ChatInput.SendButton = ChatInputSendButton;
|
|
119
127
|
ChatInput.VoiceButton = ChatInputVoiceButton;
|
package/public/ChatInput.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInput.js","sources":["src/public/ChatInput.tsx"],"sourcesContent":["import {\n type ChangeEventHandler,\n type FC,\n type ForwardedRef,\n forwardRef,\n type ForwardRefExoticComponent,\n type ReactNode,\n type RefAttributes,\n type TextareaHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport classNames from 'classnames';\n\nimport { DisabledContext, useDisabled } from '@hh.ru/magritte-common-use-disabled';\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { ChatInputContextProvider } from '@hh.ru/magritte-ui-chat-input/internal/ChatInputContext';\nimport { ModeTransition } from '@hh.ru/magritte-ui-chat-input/internal/ModeTransition';\nimport { TextInput } from '@hh.ru/magritte-ui-chat-input/internal/TextInput';\nimport { VoiceRecord } from '@hh.ru/magritte-ui-chat-input/internal/VoiceRecord';\nimport { FOCUS_PRIORITY, focusPriorityProps } from '@hh.ru/magritte-ui-chat-input/internal/focusGroup';\nimport { useRovingFocusGroup } from '@hh.ru/magritte-ui-chat-input/internal/useRovingFocusGroup';\nimport { useVoiceRecordSession } from '@hh.ru/magritte-ui-chat-input/internal/useVoiceRecordSession';\nimport { ChatInputVoiceSlotProvider, useVoiceConfig } from '@hh.ru/magritte-ui-chat-input/internal/voiceSlotRegistry';\nimport { ChatInputChips } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';\nimport { ChatInputPreview } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';\nimport { ChatInputSendButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';\nimport { ChatInputVoiceButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';\nimport { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\n\nimport styles from '../styles.less';\n\ninterface ChatInputOwnProps {\n /** Левый слот */\n leftActions?: ReactNode;\n /** Правый слот */\n rightActions?: ReactNode;\n /** Центральный нижний слот */\n centralActions?: ReactNode;\n /** Верхний слот для блока превью */\n preview?: ReactNode;\n /** Максимальная высота поля ввода в пикселях. Если не задан — высота не ограничена. */\n maxHeight?: number;\n /**\n * Раскладка поля ввода.\n * `horizontal` — ввод стоит в ряду контролов, пока содержимое помещается в одну строку,\n * и сам переезжает на свой ряд, когда перестаёт влезать.\n * `vertical` — ввод всегда на своём ряду; в горизонтальный слот его не ставим.\n * @default horizontal\n */\n layout?: 'vertical' | 'horizontal';\n /** Хендлер отправки: вызывается по Enter (Shift+Enter — перенос строки) */\n onSend?: VoidFunction;\n /** Значение поля ввода. Компонент работает только в controlled-режиме */\n value: string;\n /** Обработчик изменения значения */\n onChange: ChangeEventHandler<HTMLTextAreaElement>;\n /** Реф на корневую обёртку — для измерения размеров/позиционирования.\n * Реф на textarea (фокус и т.п.) прокидывается обычным `ref`, как у Input/TextArea */\n wrapperRef?: ForwardedRef<HTMLDivElement>;\n /** Отключает фон и обводку компонента */\n noBackground?: boolean;\n disabled?: boolean;\n 'data-qa'?: string;\n}\n\n// defaultValue исключён: компонент только controlled, uncontrolled-режим не поддерживается\nexport type ChatInputProps = ChatInputOwnProps &\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof ChatInputOwnProps | 'defaultValue'>;\n\nconst DEFAULT_ICON_PROPS = {\n borderRadius: 12,\n padding: 8,\n initialColor: 'secondary',\n} as const;\n\ninterface ChatInputComponents {\n Chips: typeof ChatInputChips;\n Preview: typeof ChatInputPreview;\n SendButton: typeof ChatInputSendButton;\n VoiceButton: typeof ChatInputVoiceButton;\n}\n\ntype ChatInputInnerProps = ChatInputProps & {\n /** Реф на textarea, переданный через forwardRef внешней обёртки */\n textareaRef: ForwardedRef<HTMLTextAreaElement>;\n};\n\nconst ChatInputInner: FC<ChatInputInnerProps> = ({\n leftActions,\n rightActions,\n centralActions,\n preview,\n maxHeight,\n layout = 'horizontal',\n onSend,\n wrapperRef,\n textareaRef,\n noBackground = false,\n disabled = false,\n 'data-qa': dataQa = 'chat-input',\n ...textareaProps\n}) => {\n const outerDisabled = useDisabled();\n const isDisabled = disabled || outerDisabled;\n const rootRef = useRef<HTMLDivElement>(null);\n const rootRefCallback = useMultipleRefs(rootRef, wrapperRef);\n // реф textarea — для возврата фокуса при выходе из режима записи\n const textareaLocalRef = useRef<HTMLTextAreaElement>(null);\n const textareaRefCallback = useMultipleRefs(textareaLocalRef, textareaRef);\n const [containerWidth, setContainerWidth] = useState<number>();\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) {\n return undefined;\n }\n const observer = new ResizeObserver((entries) => {\n const width = Math.round(entries[0]?.contentRect.width ?? 0);\n setContainerWidth((prev) => (prev === width ? prev : width));\n });\n observer.observe(root);\n return () => observer.disconnect();\n }, []);\n\n // конфиг записи регистрирует ChatInput.VoiceButton через slot-registry. Кнопка живёт в\n // text-гриде, который на время записи не размонтируется (ModeTransition лишь прячет его), —\n // поэтому регистрация и колбэки остаются живыми всю сессию, латч не нужен\n const voiceConfig = useVoiceConfig();\n\n const voiceSession = useVoiceRecordSession(voiceConfig ?? {});\n\n const contextValue = useMemo(\n () => ({\n onSend,\n startVoiceRecord: voiceSession.start,\n voiceRecordStatus: voiceSession.status,\n }),\n [onSend, voiceSession.start, voiceSession.status]\n );\n\n // режим ведём по статусу сессии, а не по наличию конфига: даже если приложение уберёт кнопку\n // по ходу записи, запись продолжается. Без кнопки запись не стартует, так что статус сам остаётся idle\n const isVoiceMode = voiceSession.status === 'recording' || voiceSession.status === 'processing';\n\n // roving-группа кнопок: один tab stop на все кнопки, внутри — стрелки по приоритетам\n const { focusStop } = useRovingFocusGroup(rootRef);\n\n // при входе в запись фокус на стоп группы (после смены слоя это галочка — первый приоритет\n // слоя записи), при возврате в текст — в textarea с курсором в конце. Фокус ставим в rAF:\n // слой режима к этому моменту уже видим (motion применил visibility), иначе focus()\n // на visibility:hidden не сработает\n const prevVoiceModeRef = useRef(isVoiceMode);\n useEffect(() => {\n const wasVoiceMode = prevVoiceModeRef.current;\n prevVoiceModeRef.current = isVoiceMode;\n if (wasVoiceMode === isVoiceMode) {\n return undefined;\n }\n const frameId = requestAnimationFrame(() => {\n if (isVoiceMode) {\n focusStop();\n return;\n }\n const textarea = textareaLocalRef.current;\n if (textarea) {\n textarea.focus();\n const caret = textarea.value.length;\n textarea.setSelectionRange(caret, caret);\n }\n });\n return () => cancelAnimationFrame(frameId);\n }, [isVoiceMode, focusStop]);\n\n return (\n <DisabledContext.Provider value={isDisabled}>\n <ChatInputContextProvider value={contextValue}>\n <div\n ref={rootRefCallback}\n className={classNames(styles.chatInput, { [styles.noBackground]: noBackground })}\n data-qa={dataQa}\n >\n <ModeTransition\n mode={isVoiceMode ? 'voice' : 'text'}\n voice={\n <VoiceRecord\n mode={voiceSession.status === 'processing' ? 'processing' : 'recording'}\n stream={voiceSession.stream}\n startedAt={voiceSession.startedAt}\n processingLabel={voiceConfig?.processingLabel}\n onComplete={voiceSession.stop}\n onCancel={voiceSession.cancel}\n completeButtonProps={voiceConfig?.completeButtonProps}\n cancelButtonProps={voiceConfig?.cancelButtonProps}\n data-qa=\"chat-input-voice-record\"\n />\n }\n text={\n <div\n className={classNames(styles.contentGrid, {\n [styles.noLeftControls]: !leftActions,\n [styles.noRightControls]: !rightActions,\n [styles.hasCentral]: !!centralActions,\n })}\n >\n {/* textarea в DOM первым намеренно: Tab снаружи входит сначала в него.\n Раскладку держит grid-area (от порядка не зависит). Кнопки слотов —\n одна roving-группа (useRovingFocusGroup): Tab видит только текущий\n стоп, внутри группы фокус ходит стрелками по приоритетам слотов */}\n <TextInput\n {...textareaProps}\n ref={textareaRefCallback}\n layout={layout}\n onSend={onSend}\n maxHeight={maxHeight}\n containerWidth={containerWidth}\n hasCentral={!!centralActions}\n disabled={isDisabled}\n hasBothSideControls={!!leftActions && !!rightActions}\n />\n {!!rightActions && (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.right} {...focusPriorityProps(FOCUS_PRIORITY.rightSlot)}>\n {rightActions}\n </div>\n </IconDefaultPropsContext>\n )}\n {!!leftActions && (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.left} {...focusPriorityProps(FOCUS_PRIORITY.leftSlot)}>\n {leftActions}\n </div>\n </IconDefaultPropsContext>\n )}\n {!!centralActions && (\n <div className={styles.central} {...focusPriorityProps(FOCUS_PRIORITY.centralSlot)}>\n {centralActions}\n </div>\n )}\n {!!preview && (\n <div className={styles.preview} {...focusPriorityProps(FOCUS_PRIORITY.previewSlot)}>\n {preview}\n </div>\n )}\n </div>\n }\n />\n </div>\n </ChatInputContextProvider>\n </DisabledContext.Provider>\n );\n};\n\n// внешняя обёртка держит slot-registry для конфига записи: кнопка (внутри слота) регистрирует\n// конфиг, ChatInputInner (ниже провайдера) читает его. forwardRef-реф на textarea прокидываем\n// вниз обычным пропом\nconst ChatInputComponent = (props: ChatInputProps, ref: ForwardedRef<HTMLTextAreaElement>) => (\n <ChatInputVoiceSlotProvider>\n <ChatInputInner {...props} textareaRef={ref} />\n </ChatInputVoiceSlotProvider>\n);\n\nconst ChatInput = forwardRef(ChatInputComponent) as ForwardRefExoticComponent<\n ChatInputProps & RefAttributes<HTMLTextAreaElement>\n> &\n ChatInputComponents;\n\nChatInput.displayName = 'ChatInput';\n\nChatInput.Chips = ChatInputChips;\nChatInput.Preview = ChatInputPreview;\nChatInput.SendButton = ChatInputSendButton;\nChatInput.VoiceButton = ChatInputVoiceButton;\n\nexport { ChatInput };\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatInput.js","sources":["src/public/ChatInput.tsx"],"sourcesContent":["import {\n type ChangeEventHandler,\n type FC,\n type ForwardedRef,\n forwardRef,\n type ForwardRefExoticComponent,\n type ReactNode,\n type RefAttributes,\n type TextareaHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport classNames from 'classnames';\n\nimport { DisabledContext, useDisabled } from '@hh.ru/magritte-common-use-disabled';\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { ChatInputContextProvider } from '@hh.ru/magritte-ui-chat-input/internal/ChatInputContext';\nimport { ModeTransition } from '@hh.ru/magritte-ui-chat-input/internal/ModeTransition';\nimport { TextInput } from '@hh.ru/magritte-ui-chat-input/internal/TextInput';\nimport { VoiceRecord } from '@hh.ru/magritte-ui-chat-input/internal/VoiceRecord';\nimport { FOCUS_PRIORITY, focusPriorityProps } from '@hh.ru/magritte-ui-chat-input/internal/focusGroup';\nimport { useRovingFocusGroup } from '@hh.ru/magritte-ui-chat-input/internal/useRovingFocusGroup';\nimport { useVoiceRecordSession } from '@hh.ru/magritte-ui-chat-input/internal/useVoiceRecordSession';\nimport { ChatInputVoiceSlotProvider, useVoiceConfig } from '@hh.ru/magritte-ui-chat-input/internal/voiceSlotRegistry';\nimport { ChatInputChips } from '@hh.ru/magritte-ui-chat-input/public/ChatInputChips';\nimport { ChatInputFile } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';\nimport { ChatInputFiles } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFiles';\nimport { ChatInputPreview } from '@hh.ru/magritte-ui-chat-input/public/ChatInputPreview';\nimport { ChatInputSendButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputSendButton';\nimport { ChatInputVoiceButton } from '@hh.ru/magritte-ui-chat-input/public/ChatInputVoiceButton';\nimport { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\n\nimport styles from '../styles.less';\n\ninterface ChatInputOwnProps {\n /** Левый слот */\n leftActions?: ReactNode;\n /** Правый слот */\n rightActions?: ReactNode;\n /** Центральный нижний слот */\n centralActions?: ReactNode;\n /** Верхний слот для блока превью */\n preview?: ReactNode;\n /** Максимальная высота поля ввода в пикселях. Если не задан — высота не ограничена. */\n maxHeight?: number;\n /**\n * Раскладка поля ввода.\n * `horizontal` — ввод стоит в ряду контролов, пока содержимое помещается в одну строку,\n * и сам переезжает на свой ряд, когда перестаёт влезать.\n * `vertical` — ввод всегда на своём ряду; в горизонтальный слот его не ставим.\n * @default horizontal\n */\n layout?: 'vertical' | 'horizontal';\n /** Хендлер отправки: вызывается по Enter (Shift+Enter — перенос строки) */\n onSend?: VoidFunction;\n /** Значение поля ввода. Компонент работает только в controlled-режиме */\n value: string;\n /** Обработчик изменения значения */\n onChange: ChangeEventHandler<HTMLTextAreaElement>;\n /** Реф на корневую обёртку — для измерения размеров/позиционирования.\n * Реф на textarea (фокус и т.п.) прокидывается обычным `ref`, как у Input/TextArea */\n wrapperRef?: ForwardedRef<HTMLDivElement>;\n /** Отключает фон и обводку компонента */\n noBackground?: boolean;\n disabled?: boolean;\n 'data-qa'?: string;\n}\n\n// defaultValue исключён: компонент только controlled, uncontrolled-режим не поддерживается\nexport type ChatInputProps = ChatInputOwnProps &\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof ChatInputOwnProps | 'defaultValue'>;\n\nconst DEFAULT_ICON_PROPS = {\n borderRadius: 12,\n padding: 8,\n initialColor: 'secondary',\n} as const;\n\ninterface ChatInputComponents {\n Chips: typeof ChatInputChips;\n File: typeof ChatInputFile;\n Files: typeof ChatInputFiles;\n Preview: typeof ChatInputPreview;\n SendButton: typeof ChatInputSendButton;\n VoiceButton: typeof ChatInputVoiceButton;\n}\n\ntype ChatInputInnerProps = ChatInputProps & {\n /** Реф на textarea, переданный через forwardRef внешней обёртки */\n textareaRef: ForwardedRef<HTMLTextAreaElement>;\n};\n\nconst ChatInputInner: FC<ChatInputInnerProps> = ({\n leftActions,\n rightActions,\n centralActions,\n preview,\n maxHeight,\n layout = 'horizontal',\n onSend,\n wrapperRef,\n textareaRef,\n noBackground = false,\n disabled = false,\n 'data-qa': dataQa = 'chat-input',\n ...textareaProps\n}) => {\n const outerDisabled = useDisabled();\n const isDisabled = disabled || outerDisabled;\n const rootRef = useRef<HTMLDivElement>(null);\n const rootRefCallback = useMultipleRefs(rootRef, wrapperRef);\n // реф textarea — для возврата фокуса при выходе из режима записи\n const textareaLocalRef = useRef<HTMLTextAreaElement>(null);\n const textareaRefCallback = useMultipleRefs(textareaLocalRef, textareaRef);\n const [containerWidth, setContainerWidth] = useState<number>();\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) {\n return undefined;\n }\n const observer = new ResizeObserver((entries) => {\n const width = Math.round(entries[0]?.contentRect.width ?? 0);\n setContainerWidth((prev) => (prev === width ? prev : width));\n });\n observer.observe(root);\n return () => observer.disconnect();\n }, []);\n\n // конфиг записи регистрирует ChatInput.VoiceButton через slot-registry. Кнопка живёт в\n // text-гриде, который на время записи не размонтируется (ModeTransition лишь прячет его), —\n // поэтому регистрация и колбэки остаются живыми всю сессию, латч не нужен\n const voiceConfig = useVoiceConfig();\n\n const voiceSession = useVoiceRecordSession(voiceConfig ?? {});\n\n const contextValue = useMemo(\n () => ({\n onSend,\n startVoiceRecord: voiceSession.start,\n voiceRecordStatus: voiceSession.status,\n }),\n [onSend, voiceSession.start, voiceSession.status]\n );\n\n // режим ведём по статусу сессии, а не по наличию конфига: даже если приложение уберёт кнопку\n // по ходу записи, запись продолжается. Без кнопки запись не стартует, так что статус сам остаётся idle\n const isVoiceMode = voiceSession.status === 'recording' || voiceSession.status === 'processing';\n\n // roving-группа кнопок: один tab stop на все кнопки, внутри — стрелки по приоритетам\n const { focusStop } = useRovingFocusGroup(rootRef);\n\n // при входе в запись фокус на стоп группы (после смены слоя это галочка — первый приоритет\n // слоя записи), при возврате в текст — в textarea с курсором в конце. Фокус ставим в rAF:\n // слой режима к этому моменту уже видим (motion применил visibility), иначе focus()\n // на visibility:hidden не сработает\n const prevVoiceModeRef = useRef(isVoiceMode);\n useEffect(() => {\n const wasVoiceMode = prevVoiceModeRef.current;\n prevVoiceModeRef.current = isVoiceMode;\n if (wasVoiceMode === isVoiceMode) {\n return undefined;\n }\n const frameId = requestAnimationFrame(() => {\n if (isVoiceMode) {\n focusStop();\n return;\n }\n const textarea = textareaLocalRef.current;\n if (textarea) {\n textarea.focus();\n const caret = textarea.value.length;\n textarea.setSelectionRange(caret, caret);\n }\n });\n return () => cancelAnimationFrame(frameId);\n }, [isVoiceMode, focusStop]);\n\n return (\n <DisabledContext.Provider value={isDisabled}>\n <ChatInputContextProvider value={contextValue}>\n <div\n ref={rootRefCallback}\n className={classNames(styles.chatInput, { [styles.noBackground]: noBackground })}\n data-qa={dataQa}\n >\n <ModeTransition\n mode={isVoiceMode ? 'voice' : 'text'}\n voice={\n <VoiceRecord\n mode={voiceSession.status === 'processing' ? 'processing' : 'recording'}\n stream={voiceSession.stream}\n startedAt={voiceSession.startedAt}\n processingLabel={voiceConfig?.processingLabel}\n onComplete={voiceSession.stop}\n onCancel={voiceSession.cancel}\n completeButtonProps={voiceConfig?.completeButtonProps}\n cancelButtonProps={voiceConfig?.cancelButtonProps}\n data-qa=\"chat-input-voice-record\"\n />\n }\n text={\n <div\n className={classNames(styles.contentGrid, {\n [styles.noLeftControls]: !leftActions,\n [styles.noRightControls]: !rightActions,\n [styles.hasCentral]: !!centralActions,\n })}\n >\n {/* textarea в DOM первым намеренно: Tab снаружи входит сначала в него.\n Раскладку держит grid-area (от порядка не зависит). Кнопки слотов —\n одна roving-группа (useRovingFocusGroup): Tab видит только текущий\n стоп, внутри группы фокус ходит стрелками по приоритетам слотов */}\n <TextInput\n {...textareaProps}\n ref={textareaRefCallback}\n layout={layout}\n onSend={onSend}\n maxHeight={maxHeight}\n containerWidth={containerWidth}\n hasCentral={!!centralActions}\n disabled={isDisabled}\n hasBothSideControls={!!leftActions && !!rightActions}\n />\n {!!rightActions && (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.right} {...focusPriorityProps(FOCUS_PRIORITY.rightSlot)}>\n {rightActions}\n </div>\n </IconDefaultPropsContext>\n )}\n {!!leftActions && (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.left} {...focusPriorityProps(FOCUS_PRIORITY.leftSlot)}>\n {leftActions}\n </div>\n </IconDefaultPropsContext>\n )}\n {!!centralActions && (\n <div className={styles.central} {...focusPriorityProps(FOCUS_PRIORITY.centralSlot)}>\n {centralActions}\n </div>\n )}\n {!!preview && (\n <div className={styles.preview} {...focusPriorityProps(FOCUS_PRIORITY.previewSlot)}>\n {preview}\n </div>\n )}\n </div>\n }\n />\n </div>\n </ChatInputContextProvider>\n </DisabledContext.Provider>\n );\n};\n\n// внешняя обёртка держит slot-registry для конфига записи: кнопка (внутри слота) регистрирует\n// конфиг, ChatInputInner (ниже провайдера) читает его. forwardRef-реф на textarea прокидываем\n// вниз обычным пропом\nconst ChatInputComponent = (props: ChatInputProps, ref: ForwardedRef<HTMLTextAreaElement>) => (\n <ChatInputVoiceSlotProvider>\n <ChatInputInner {...props} textareaRef={ref} />\n </ChatInputVoiceSlotProvider>\n);\n\nconst ChatInput = forwardRef(ChatInputComponent) as ForwardRefExoticComponent<\n ChatInputProps & RefAttributes<HTMLTextAreaElement>\n> &\n ChatInputComponents;\n\nChatInput.displayName = 'ChatInput';\n\nChatInput.Chips = ChatInputChips;\nChatInput.File = ChatInputFile;\nChatInput.Files = ChatInputFiles;\nChatInput.Preview = ChatInputPreview;\nChatInput.SendButton = ChatInputSendButton;\nChatInput.VoiceButton = ChatInputVoiceButton;\n\nexport { ChatInput };\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
package/public/ChatInputChips.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import './../index.css';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { isValidElement
|
|
3
|
+
import { isValidElement } from 'react';
|
|
4
|
+
import { flattenFragments } from '../internal/flattenFragments.js';
|
|
4
5
|
import { ChipDefaultPropsContext } from '@hh.ru/magritte-ui-chips';
|
|
5
6
|
import { ScrollableContainer } from '@hh.ru/magritte-ui-scrollable-container';
|
|
6
|
-
import { s as styles } from '../styles-
|
|
7
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
7
8
|
|
|
8
9
|
const CHIP_DEFAULT_PROPS = { size: 'extra-small' };
|
|
9
|
-
const flattenFragments = (children) => Children.toArray(children).flatMap((child) => isValidElement(child) && child.type === Fragment
|
|
10
|
-
? flattenFragments(child.props.children)
|
|
11
|
-
: child);
|
|
12
10
|
const ChatInputChips = ({ children }) => (jsx("div", { className: styles.chipsContainer, children: jsx(ChipDefaultPropsContext, { props: CHIP_DEFAULT_PROPS, children: jsx(ScrollableContainer, { children: jsx(ScrollableContainer.DefaultLayout, { size: "small", fadeOnMobile: true, children: jsx(ScrollableContainer.Gallery, { children: jsx("div", { className: styles.chips, children: flattenFragments(children).map((child, index) => (jsx(ScrollableContainer.Item, { children: child }, (isValidElement(child) && child.key) || index))) }) }) }) }) }) }));
|
|
13
11
|
ChatInputChips.displayName = 'ChatInputChips';
|
|
14
12
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInputChips.js","sources":["src/public/ChatInputChips.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"ChatInputChips.js","sources":["src/public/ChatInputChips.tsx"],"sourcesContent":["import { isValidElement, type FC, type ReactNode } from 'react';\n\nimport { flattenFragments } from '@hh.ru/magritte-ui-chat-input/internal/flattenFragments';\nimport { ChipDefaultPropsContext } from '@hh.ru/magritte-ui-chips';\nimport { ScrollableContainer } from '@hh.ru/magritte-ui-scrollable-container';\n\nimport styles from '../styles.less';\n\nexport interface ChatInputChipsProps {\n /** Чипсы, размещаются в один ряд с возможностью горизонтального скролла */\n children: ReactNode;\n}\n\nconst CHIP_DEFAULT_PROPS = { size: 'extra-small' } as const;\n\nexport const ChatInputChips: FC<ChatInputChipsProps> = ({ children }) => (\n <div className={styles.chipsContainer}>\n <ChipDefaultPropsContext props={CHIP_DEFAULT_PROPS}>\n <ScrollableContainer>\n <ScrollableContainer.DefaultLayout size=\"small\" fadeOnMobile>\n <ScrollableContainer.Gallery>\n <div className={styles.chips}>\n {/* Children.toArray сохраняет ключи детей — переносим их на обёртку,\n чтобы удаление чипса из середины не сдвигало стейт соседей */}\n {flattenFragments(children).map((child, index) => (\n <ScrollableContainer.Item key={(isValidElement(child) && child.key) || index}>\n {child}\n </ScrollableContainer.Item>\n ))}\n </div>\n </ScrollableContainer.Gallery>\n </ScrollableContainer.DefaultLayout>\n </ScrollableContainer>\n </ChipDefaultPropsContext>\n </div>\n);\n\nChatInputChips.displayName = 'ChatInputChips';\n"],"names":["_jsx"],"mappings":";;;;;;;AAaA,MAAM,kBAAkB,GAAG,EAAE,IAAI,EAAE,aAAa,EAAW,CAAC;MAE/C,cAAc,GAA4B,CAAC,EAAE,QAAQ,EAAE,MAChEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,cAAc,EAAA,QAAA,EACjCA,GAAC,CAAA,uBAAuB,EAAC,EAAA,KAAK,EAAE,kBAAkB,EAAA,QAAA,EAC9CA,IAAC,mBAAmB,EAAA,EAAA,QAAA,EAChBA,IAAC,mBAAmB,CAAC,aAAa,EAAC,EAAA,IAAI,EAAC,OAAO,EAAC,YAAY,EACxD,IAAA,EAAA,QAAA,EAAAA,GAAA,CAAC,mBAAmB,CAAC,OAAO,EACxB,EAAA,QAAA,EAAAA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,KAAK,YAGvB,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,MACzCA,GAAC,CAAA,mBAAmB,CAAC,IAAI,EACpB,EAAA,QAAA,EAAA,KAAK,IADqB,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,CAEjD,CAC9B,CAAC,EACA,CAAA,EAAA,CACoB,GACE,EAClB,CAAA,EAAA,CACA,EACxB,CAAA,EACR;AAEF,cAAc,CAAC,WAAW,GAAG,gBAAgB;;;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type HTMLAttributes, type MouseEventHandler, type ReactNode } from 'react';
|
|
2
|
+
import { type ChatInputButtonAria } from '@hh.ru/magritte-ui-chat-input/types';
|
|
3
|
+
export type ChatInputFileState = 'loading' | 'loaded' | 'invalid';
|
|
4
|
+
export type ChatInputFileType = 'doc' | 'video' | 'image';
|
|
5
|
+
export interface ChatInputFileProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'className'> {
|
|
6
|
+
/** Имя файла. Если передана строка, при нехватке места обрезается основа имени, а расширение
|
|
7
|
+
* остаётся видимым целиком */
|
|
8
|
+
name?: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Строка под именем (например, для размера файла или текста ошибки).
|
|
11
|
+
* Для `type="image"` не отображается
|
|
12
|
+
*/
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Состояние файла
|
|
16
|
+
* @default loaded
|
|
17
|
+
*/
|
|
18
|
+
state?: ChatInputFileState;
|
|
19
|
+
/**
|
|
20
|
+
* Тип файла: `doc` и `video` — карточка с иконкой и именем, `image` — квадратное превью
|
|
21
|
+
* @default doc
|
|
22
|
+
*/
|
|
23
|
+
type?: ChatInputFileType;
|
|
24
|
+
/**
|
|
25
|
+
* Превью, показывается для `type="image"` в состоянии `loaded`: url картинки или сам файл (`File`/`Blob`).
|
|
26
|
+
* Для файла компонент локально создаёт object URL и сам его отзывает — загружать файл на сервер
|
|
27
|
+
* ради превью не нужно
|
|
28
|
+
*/
|
|
29
|
+
preview?: string | Blob;
|
|
30
|
+
/** Alt превью. По умолчанию — имя файла, если оно строка */
|
|
31
|
+
previewAlt?: string;
|
|
32
|
+
/** Обработчик удаления файла. Без него кнопка удаления файла не показывается */
|
|
33
|
+
onRemove?: MouseEventHandler<HTMLButtonElement>;
|
|
34
|
+
/** aria/data-qa пропсы кнопки удаления файла. Своя `aria-label` перекрывает дефолтную */
|
|
35
|
+
removeButtonProps?: ChatInputButtonAria;
|
|
36
|
+
/**
|
|
37
|
+
* Значение data-qa
|
|
38
|
+
* @default chat-input-file
|
|
39
|
+
*/
|
|
40
|
+
'data-qa'?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Приложенный к сообщению файл */
|
|
43
|
+
export declare const ChatInputFile: import("react").ForwardRefExoticComponent<ChatInputFileProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import './../index.css';
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useState } from 'react';
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
import { useTranslation } from '@hh.ru/magritte-common-use-translation';
|
|
6
|
+
import { Cell, CellText } from '@hh.ru/magritte-ui-cell';
|
|
7
|
+
import { useObjectUrl } from '../internal/useObjectUrl.js';
|
|
8
|
+
import { CheckCircleOutlinedSize16, ExclamationTriangleOutlinedSize16, ImageOutlinedSize24, CrossOutlinedSize16, VideocameraOutlinedSize24, DocumentOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';
|
|
9
|
+
import { LinkDefaultPropsContext } from '@hh.ru/magritte-ui-link';
|
|
10
|
+
import { Loader } from '@hh.ru/magritte-ui-loader';
|
|
11
|
+
import { TextDefaultPropsContext } from '@hh.ru/magritte-ui-typography';
|
|
12
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
13
|
+
|
|
14
|
+
const splitFileName = (name) => {
|
|
15
|
+
const dotIndex = name.lastIndexOf('.');
|
|
16
|
+
// точка в начале (.gitignore) или в конце (file.) — расширения нет, имя целиком
|
|
17
|
+
if (dotIndex <= 0 || dotIndex === name.length - 1) {
|
|
18
|
+
return { base: name, extension: '' };
|
|
19
|
+
}
|
|
20
|
+
return { base: name.slice(0, dotIndex), extension: name.slice(dotIndex) };
|
|
21
|
+
};
|
|
22
|
+
const FileName = ({ name }) => {
|
|
23
|
+
if (typeof name !== 'string') {
|
|
24
|
+
return jsx(Fragment, { children: name });
|
|
25
|
+
}
|
|
26
|
+
const { base, extension } = splitFileName(name);
|
|
27
|
+
// основа сжимается с многоточием, расширение не сжимается; типографику даёт CellText.
|
|
28
|
+
// имя без расширения обрезается так же, целиком
|
|
29
|
+
return (jsxs("span", { className: styles.fileName, children: [jsx("span", { className: styles.fileNameBase, children: base }), extension && jsx("span", { className: styles.fileNameExtension, children: extension })] }));
|
|
30
|
+
};
|
|
31
|
+
const STATUS_ICON = {
|
|
32
|
+
loading: jsx(Loader, { size: 16 }),
|
|
33
|
+
loaded: jsx(CheckCircleOutlinedSize16, { initialColor: "positive" }),
|
|
34
|
+
invalid: jsx(ExclamationTriangleOutlinedSize16, { initialColor: "negative" }),
|
|
35
|
+
};
|
|
36
|
+
const LINK_DEFAULT_PROPS = { typography: 'label-3-regular', inline: true };
|
|
37
|
+
// строку оформляет CellText, а Text, переданный пользователем в name/description, получает те же дефолты.
|
|
38
|
+
// ellipsis — для Text: блочный элемент не обрезается text-overflow родителя
|
|
39
|
+
const NAME_TEXT_PROPS = { typography: 'label-3-regular', style: 'primary', ellipsis: true };
|
|
40
|
+
const DESCRIPTION_TEXT_PROPS = { typography: 'label-3-regular', style: 'secondary', ellipsis: true };
|
|
41
|
+
/** Приложенный к сообщению файл */
|
|
42
|
+
const ChatInputFile = forwardRef(({ 'data-qa': dataQa = 'chat-input-file', description, name, onRemove, preview, previewAlt, removeButtonProps, state = 'loaded', type = 'doc', ...props }, ref) => {
|
|
43
|
+
const removeLabel = useTranslation('ChatInput', 'removeFile');
|
|
44
|
+
const isImage = type === 'image';
|
|
45
|
+
// object URL создаём только для плитки картинки — карточкам он не нужен
|
|
46
|
+
const previewSrc = useObjectUrl(isImage ? preview : undefined);
|
|
47
|
+
// битая картинка — показываем заглушку; сбрасывается сменой src или уходом из loaded,
|
|
48
|
+
// чтобы тот же url (например, ещё не готовое серверное превью) загрузился повторно
|
|
49
|
+
const [failedSrc, setFailedSrc] = useState();
|
|
50
|
+
if (state !== 'loaded' && failedSrc !== undefined) {
|
|
51
|
+
setFailedSrc(undefined);
|
|
52
|
+
}
|
|
53
|
+
let content;
|
|
54
|
+
if (isImage) {
|
|
55
|
+
const showPreview = state === 'loaded' && !!previewSrc && previewSrc !== failedSrc;
|
|
56
|
+
let placeholder = null;
|
|
57
|
+
if (state === 'loading') {
|
|
58
|
+
placeholder = jsx(Loader, { size: 24 });
|
|
59
|
+
}
|
|
60
|
+
else if (!showPreview) {
|
|
61
|
+
placeholder = jsx(ImageOutlinedSize24, { initialColor: "tertiary" });
|
|
62
|
+
}
|
|
63
|
+
content = (jsx("div", { className: classNames(styles.fileTile, { [styles.fileTilePlaceholder]: !showPreview }), children: showPreview ? (jsx("img", { className: styles.fileTileImage, src: previewSrc, alt: previewAlt ?? (typeof name === 'string' ? name : ''), onError: () => setFailedSrc(previewSrc) })) : (placeholder) }));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const Icon = type === 'video' ? VideocameraOutlinedSize24 : DocumentOutlinedSize24;
|
|
67
|
+
content = (jsx("div", { className: classNames(styles.fileCard, { [styles.fileCardRemovable]: !!onRemove }), children: jsxs(Cell, { align: "center", horPadding: false, vertPadding: false, left: jsx(Icon, { initialColor: "secondary", backgroundStyle: "secondary", padding: 12, borderRadius: 8 }), children: [!!name && (jsx(CellText, { type: "title", typography: "label-3-regular", style: "primary", maxLines: 1, "data-qa": "chat-input-file-name", children: jsx(TextDefaultPropsContext, { props: NAME_TEXT_PROPS, children: jsx(FileName, { name: name }) }) })), !!description && (jsx(CellText, { type: "subtitle", style: "secondary", maxLines: 1, left: STATUS_ICON[state], "data-qa": "chat-input-file-description", children: jsx(TextDefaultPropsContext, { props: DESCRIPTION_TEXT_PROPS, children: jsx(LinkDefaultPropsContext, { props: LINK_DEFAULT_PROPS, children: description }) }) }))] }) }));
|
|
68
|
+
}
|
|
69
|
+
return (jsxs("div", { ...props, className: styles.file, "data-qa": dataQa, ref: ref, children: [content, onRemove && (jsx("span", { className: styles.fileRemove, children: jsx(CrossOutlinedSize16, { "data-qa": "chat-input-file-remove", ...removeButtonProps, "aria-label": removeButtonProps?.['aria-label'] ?? removeLabel, initialColor: "primary", backgroundStyle: "secondary", borderRadius: 8, padding: 2, onClick: onRemove }) }))] }));
|
|
70
|
+
});
|
|
71
|
+
ChatInputFile.displayName = 'ChatInputFile';
|
|
72
|
+
|
|
73
|
+
export { ChatInputFile };
|
|
74
|
+
//# sourceMappingURL=ChatInputFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatInputFile.js","sources":["src/public/ChatInputFile.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type MouseEventHandler, type ReactNode, useState } from 'react';\nimport classNames from 'classnames';\n\nimport { useTranslation } from '@hh.ru/magritte-common-use-translation';\nimport { Cell, CellText } from '@hh.ru/magritte-ui-cell';\nimport { useObjectUrl } from '@hh.ru/magritte-ui-chat-input/internal/useObjectUrl';\nimport { type ChatInputButtonAria } from '@hh.ru/magritte-ui-chat-input/types';\nimport {\n CheckCircleOutlinedSize16,\n CrossOutlinedSize16,\n DocumentOutlinedSize24,\n ExclamationTriangleOutlinedSize16,\n ImageOutlinedSize24,\n VideocameraOutlinedSize24,\n} from '@hh.ru/magritte-ui-icon/icon';\nimport { LinkDefaultPropsContext } from '@hh.ru/magritte-ui-link';\nimport { Loader } from '@hh.ru/magritte-ui-loader';\nimport { TextDefaultPropsContext } from '@hh.ru/magritte-ui-typography';\n\nimport styles from '../styles.less';\n\nexport type ChatInputFileState = 'loading' | 'loaded' | 'invalid';\n\nexport type ChatInputFileType = 'doc' | 'video' | 'image';\n\nexport interface ChatInputFileProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'className'> {\n /** Имя файла. Если передана строка, при нехватке места обрезается основа имени, а расширение\n * остаётся видимым целиком */\n name?: ReactNode;\n /**\n * Строка под именем (например, для размера файла или текста ошибки).\n * Для `type=\"image\"` не отображается\n */\n description?: ReactNode;\n /**\n * Состояние файла\n * @default loaded\n */\n state?: ChatInputFileState;\n /**\n * Тип файла: `doc` и `video` — карточка с иконкой и именем, `image` — квадратное превью\n * @default doc\n */\n type?: ChatInputFileType;\n /**\n * Превью, показывается для `type=\"image\"` в состоянии `loaded`: url картинки или сам файл (`File`/`Blob`).\n * Для файла компонент локально создаёт object URL и сам его отзывает — загружать файл на сервер\n * ради превью не нужно\n */\n preview?: string | Blob;\n /** Alt превью. По умолчанию — имя файла, если оно строка */\n previewAlt?: string;\n /** Обработчик удаления файла. Без него кнопка удаления файла не показывается */\n onRemove?: MouseEventHandler<HTMLButtonElement>;\n /** aria/data-qa пропсы кнопки удаления файла. Своя `aria-label` перекрывает дефолтную */\n removeButtonProps?: ChatInputButtonAria;\n /**\n * Значение data-qa\n * @default chat-input-file\n */\n 'data-qa'?: string;\n}\n\nconst splitFileName = (name: string): { base: string; extension: string } => {\n const dotIndex = name.lastIndexOf('.');\n // точка в начале (.gitignore) или в конце (file.) — расширения нет, имя целиком\n if (dotIndex <= 0 || dotIndex === name.length - 1) {\n return { base: name, extension: '' };\n }\n return { base: name.slice(0, dotIndex), extension: name.slice(dotIndex) };\n};\n\nconst FileName = ({ name }: { name: ReactNode }) => {\n if (typeof name !== 'string') {\n return <>{name}</>;\n }\n const { base, extension } = splitFileName(name);\n // основа сжимается с многоточием, расширение не сжимается; типографику даёт CellText.\n // имя без расширения обрезается так же, целиком\n return (\n <span className={styles.fileName}>\n <span className={styles.fileNameBase}>{base}</span>\n {extension && <span className={styles.fileNameExtension}>{extension}</span>}\n </span>\n );\n};\n\nconst STATUS_ICON: Record<ChatInputFileState, ReactNode> = {\n loading: <Loader size={16} />,\n loaded: <CheckCircleOutlinedSize16 initialColor=\"positive\" />,\n invalid: <ExclamationTriangleOutlinedSize16 initialColor=\"negative\" />,\n};\n\nconst LINK_DEFAULT_PROPS = { typography: 'label-3-regular', inline: true } as const;\n\n// строку оформляет CellText, а Text, переданный пользователем в name/description, получает те же дефолты.\n// ellipsis — для Text: блочный элемент не обрезается text-overflow родителя\nconst NAME_TEXT_PROPS = { typography: 'label-3-regular', style: 'primary', ellipsis: true } as const;\nconst DESCRIPTION_TEXT_PROPS = { typography: 'label-3-regular', style: 'secondary', ellipsis: true } as const;\n\n/** Приложенный к сообщению файл */\nexport const ChatInputFile = forwardRef<HTMLDivElement, ChatInputFileProps>(\n (\n {\n 'data-qa': dataQa = 'chat-input-file',\n description,\n name,\n onRemove,\n preview,\n previewAlt,\n removeButtonProps,\n state = 'loaded',\n type = 'doc',\n ...props\n },\n ref\n ) => {\n const removeLabel = useTranslation('ChatInput', 'removeFile');\n const isImage = type === 'image';\n // object URL создаём только для плитки картинки — карточкам он не нужен\n const previewSrc = useObjectUrl(isImage ? preview : undefined);\n // битая картинка — показываем заглушку; сбрасывается сменой src или уходом из loaded,\n // чтобы тот же url (например, ещё не готовое серверное превью) загрузился повторно\n const [failedSrc, setFailedSrc] = useState<string>();\n if (state !== 'loaded' && failedSrc !== undefined) {\n setFailedSrc(undefined);\n }\n\n let content: ReactNode;\n if (isImage) {\n const showPreview = state === 'loaded' && !!previewSrc && previewSrc !== failedSrc;\n let placeholder: ReactNode = null;\n if (state === 'loading') {\n placeholder = <Loader size={24} />;\n } else if (!showPreview) {\n placeholder = <ImageOutlinedSize24 initialColor=\"tertiary\" />;\n }\n content = (\n <div className={classNames(styles.fileTile, { [styles.fileTilePlaceholder]: !showPreview })}>\n {showPreview ? (\n <img\n className={styles.fileTileImage}\n src={previewSrc}\n alt={previewAlt ?? (typeof name === 'string' ? name : '')}\n onError={() => setFailedSrc(previewSrc)}\n />\n ) : (\n placeholder\n )}\n </div>\n );\n } else {\n const Icon = type === 'video' ? VideocameraOutlinedSize24 : DocumentOutlinedSize24;\n content = (\n <div className={classNames(styles.fileCard, { [styles.fileCardRemovable]: !!onRemove })}>\n <Cell\n align=\"center\"\n horPadding={false}\n vertPadding={false}\n left={\n <Icon initialColor=\"secondary\" backgroundStyle=\"secondary\" padding={12} borderRadius={8} />\n }\n >\n {!!name && (\n <CellText\n type=\"title\"\n typography=\"label-3-regular\"\n style=\"primary\"\n maxLines={1}\n data-qa=\"chat-input-file-name\"\n >\n <TextDefaultPropsContext props={NAME_TEXT_PROPS}>\n <FileName name={name} />\n </TextDefaultPropsContext>\n </CellText>\n )}\n {!!description && (\n <CellText\n type=\"subtitle\"\n style=\"secondary\"\n maxLines={1}\n left={STATUS_ICON[state]}\n data-qa=\"chat-input-file-description\"\n >\n <TextDefaultPropsContext props={DESCRIPTION_TEXT_PROPS}>\n <LinkDefaultPropsContext props={LINK_DEFAULT_PROPS}>\n {description}\n </LinkDefaultPropsContext>\n </TextDefaultPropsContext>\n </CellText>\n )}\n </Cell>\n </div>\n );\n }\n\n return (\n <div {...props} className={styles.file} data-qa={dataQa} ref={ref}>\n {content}\n {onRemove && (\n <span className={styles.fileRemove}>\n <CrossOutlinedSize16\n data-qa=\"chat-input-file-remove\"\n {...removeButtonProps}\n aria-label={removeButtonProps?.['aria-label'] ?? removeLabel}\n initialColor=\"primary\"\n backgroundStyle=\"secondary\"\n borderRadius={8}\n padding={2}\n onClick={onRemove}\n />\n </span>\n )}\n </div>\n );\n }\n);\n\nChatInputFile.displayName = 'ChatInputFile';\n"],"names":["_jsx","_Fragment","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type FC, type ReactNode } from 'react';
|
|
2
|
+
export interface ChatInputFilesProps {
|
|
3
|
+
/** Файлы (`ChatInput.File`), размещаются в один ряд с возможностью горизонтального скролла */
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export declare const ChatInputFiles: FC<ChatInputFilesProps>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import './../index.css';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { isValidElement } from 'react';
|
|
4
|
+
import { flattenFragments } from '../internal/flattenFragments.js';
|
|
5
|
+
import { ScrollableContainer } from '@hh.ru/magritte-ui-scrollable-container';
|
|
6
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
7
|
+
|
|
8
|
+
const ChatInputFiles = ({ children }) => (jsx("div", { className: styles.filesContainer, "data-qa": "chat-input-files", children: jsx(ScrollableContainer, { correction: 11, children: jsx(ScrollableContainer.DefaultLayout, { size: "small", noFadeOnDesktop: true, buttonsOffset: 8, buttonsOnHover: true, children: jsx(ScrollableContainer.Gallery, { children: jsx("div", { className: styles.files, children: flattenFragments(children).map((child, index) => (jsx(ScrollableContainer.Item, { scrollToItemOnFocus: true, children: child }, (isValidElement(child) && child.key) || index))) }) }) }) }) }));
|
|
9
|
+
ChatInputFiles.displayName = 'ChatInputFiles';
|
|
10
|
+
|
|
11
|
+
export { ChatInputFiles };
|
|
12
|
+
//# sourceMappingURL=ChatInputFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatInputFiles.js","sources":["src/public/ChatInputFiles.tsx"],"sourcesContent":["import { isValidElement, type FC, type ReactNode } from 'react';\n\nimport { flattenFragments } from '@hh.ru/magritte-ui-chat-input/internal/flattenFragments';\nimport { ScrollableContainer } from '@hh.ru/magritte-ui-scrollable-container';\n\nimport styles from '../styles.less';\n\nexport interface ChatInputFilesProps {\n /** Файлы (`ChatInput.File`), размещаются в один ряд с возможностью горизонтального скролла */\n children: ReactNode;\n}\n\nexport const ChatInputFiles: FC<ChatInputFilesProps> = ({ children }) => (\n <div className={styles.filesContainer} data-qa=\"chat-input-files\">\n {/* область прокрутки выходит за паддинг ChatInput (12px) до его обводки (1px), чтобы файлы\n обрезались краем компонента, но не перекрывали обводку; в крайних положениях контент отступает\n от краёв на те же 12px */}\n <ScrollableContainer correction={11}>\n {/* в макете у ряда файлов нет краевых фейдов: на десктопе оставляем только кнопки листания,\n на мобильных фейды и так выключены по умолчанию. Кнопки — на 8px внутрь от края ряда\n (20px от края ChatInput) и появляются только при наведении на ряд */}\n <ScrollableContainer.DefaultLayout size=\"small\" noFadeOnDesktop buttonsOffset={8} buttonsOnHover>\n <ScrollableContainer.Gallery>\n <div className={styles.files}>\n {/* ключи детей переносим на обёртку, чтобы удаление файла из середины\n не сдвигало стейт соседей; при фокусе внутри файла (крестик, с клавиатуры)\n подскролливаем к нему */}\n {flattenFragments(children).map((child, index) => (\n <ScrollableContainer.Item\n key={(isValidElement(child) && child.key) || index}\n scrollToItemOnFocus\n >\n {child}\n </ScrollableContainer.Item>\n ))}\n </div>\n </ScrollableContainer.Gallery>\n </ScrollableContainer.DefaultLayout>\n </ScrollableContainer>\n </div>\n);\n\nChatInputFiles.displayName = 'ChatInputFiles';\n"],"names":["_jsx"],"mappings":";;;;;;MAYa,cAAc,GAA4B,CAAC,EAAE,QAAQ,EAAE,MAChEA,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,cAAc,EAAU,SAAA,EAAA,kBAAkB,EAI7D,QAAA,EAAAA,GAAA,CAAC,mBAAmB,EAAA,EAAC,UAAU,EAAE,EAAE,YAI/BA,GAAC,CAAA,mBAAmB,CAAC,aAAa,EAAA,EAAC,IAAI,EAAC,OAAO,EAAC,eAAe,EAAC,IAAA,EAAA,aAAa,EAAE,CAAC,EAAE,cAAc,kBAC5FA,GAAC,CAAA,mBAAmB,CAAC,OAAO,EACxB,EAAA,QAAA,EAAAA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,KAAK,EAAA,QAAA,EAIvB,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,MACzCA,GAAA,CAAC,mBAAmB,CAAC,IAAI,EAAA,EAErB,mBAAmB,EAElB,IAAA,EAAA,QAAA,EAAA,KAAK,IAHD,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,CAI3B,CAC9B,CAAC,EAAA,CACA,GACoB,EACE,CAAA,EAAA,CAClB,EACpB,CAAA,EACR;AAEF,cAAc,CAAC,WAAW,GAAG,gBAAgB;;;;"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import './../index.css';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
3
|
import { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';
|
|
4
|
-
import {
|
|
4
|
+
import { TextDefaultPropsContext } from '@hh.ru/magritte-ui-typography';
|
|
5
|
+
import { s as styles } from '../styles-BHWYKmPT.js';
|
|
5
6
|
|
|
6
7
|
const DEFAULT_ICON_PROPS = {
|
|
7
8
|
initialColor: 'secondary',
|
|
8
9
|
padding: 8,
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
+
// строку оформляют стили слота, а Text, переданный пользователем в title/subtitle, получает те же дефолты.
|
|
12
|
+
// ellipsis — для Text: блочный элемент не обрезается text-overflow родителя
|
|
13
|
+
const TITLE_TEXT_PROPS = { typography: 'subtitle-3-semibold', style: 'primary' };
|
|
14
|
+
const SUBTITLE_TEXT_PROPS = { typography: 'label-3-regular', style: 'secondary', ellipsis: true };
|
|
15
|
+
const ChatInputPreview = ({ title, subtitle, leftActions, rightActions }) => (jsx(IconDefaultPropsContext, { props: DEFAULT_ICON_PROPS, children: jsxs("div", { className: styles.previewBlock, children: [!!leftActions && jsx("div", { className: styles.previewSide, children: leftActions }), jsxs("div", { className: styles.previewContent, children: [!!title && (jsx(TextDefaultPropsContext, { props: TITLE_TEXT_PROPS, children: jsx("div", { className: styles.previewTitle, children: title }) })), !!subtitle && (jsx(TextDefaultPropsContext, { props: SUBTITLE_TEXT_PROPS, children: jsx("div", { className: styles.previewSubtitle, children: subtitle }) }))] }), !!rightActions && jsx("div", { className: styles.previewSide, children: rightActions })] }) }));
|
|
11
16
|
ChatInputPreview.displayName = 'ChatInputPreview';
|
|
12
17
|
|
|
13
18
|
export { ChatInputPreview };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInputPreview.js","sources":["src/public/ChatInputPreview.tsx"],"sourcesContent":["import { type FC, type ReactNode } from 'react';\n\nimport { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\n\nimport styles from '../styles.less';\n\nexport interface ChatInputPreviewProps {\n /** Заголовок в центральной секции, типографика subtitle-3-semibold */\n title?: ReactNode;\n /** Подзаголовок под title, типографика label-3-regular; обрезается многоточием */\n subtitle?: ReactNode;\n /** Слот левой секции, обычно иконка */\n leftActions?: ReactNode;\n /** Слот правой секции, обычно иконка */\n rightActions?: ReactNode;\n}\n\nconst DEFAULT_ICON_PROPS = {\n initialColor: 'secondary',\n padding: 8,\n} as const;\n\nexport const ChatInputPreview: FC<ChatInputPreviewProps> = ({ title, subtitle, leftActions, rightActions }) => (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.previewBlock}>\n {!!leftActions && <div className={styles.previewSide}>{leftActions}</div>}\n <div className={styles.previewContent}>\n {!!title && <div className={styles.previewTitle}>{title}</div
|
|
1
|
+
{"version":3,"file":"ChatInputPreview.js","sources":["src/public/ChatInputPreview.tsx"],"sourcesContent":["import { type FC, type ReactNode } from 'react';\n\nimport { IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\nimport { TextDefaultPropsContext } from '@hh.ru/magritte-ui-typography';\n\nimport styles from '../styles.less';\n\nexport interface ChatInputPreviewProps {\n /** Заголовок в центральной секции, типографика subtitle-3-semibold */\n title?: ReactNode;\n /** Подзаголовок под title, типографика label-3-regular; обрезается многоточием */\n subtitle?: ReactNode;\n /** Слот левой секции, обычно иконка */\n leftActions?: ReactNode;\n /** Слот правой секции, обычно иконка */\n rightActions?: ReactNode;\n}\n\nconst DEFAULT_ICON_PROPS = {\n initialColor: 'secondary',\n padding: 8,\n} as const;\n\n// строку оформляют стили слота, а Text, переданный пользователем в title/subtitle, получает те же дефолты.\n// ellipsis — для Text: блочный элемент не обрезается text-overflow родителя\nconst TITLE_TEXT_PROPS = { typography: 'subtitle-3-semibold', style: 'primary' } as const;\nconst SUBTITLE_TEXT_PROPS = { typography: 'label-3-regular', style: 'secondary', ellipsis: true } as const;\n\nexport const ChatInputPreview: FC<ChatInputPreviewProps> = ({ title, subtitle, leftActions, rightActions }) => (\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS}>\n <div className={styles.previewBlock}>\n {!!leftActions && <div className={styles.previewSide}>{leftActions}</div>}\n <div className={styles.previewContent}>\n {!!title && (\n <TextDefaultPropsContext props={TITLE_TEXT_PROPS}>\n <div className={styles.previewTitle}>{title}</div>\n </TextDefaultPropsContext>\n )}\n {!!subtitle && (\n <TextDefaultPropsContext props={SUBTITLE_TEXT_PROPS}>\n <div className={styles.previewSubtitle}>{subtitle}</div>\n </TextDefaultPropsContext>\n )}\n </div>\n {!!rightActions && <div className={styles.previewSide}>{rightActions}</div>}\n </div>\n </IconDefaultPropsContext>\n);\n\nChatInputPreview.displayName = 'ChatInputPreview';\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;AAkBA,MAAM,kBAAkB,GAAG;AACvB,IAAA,YAAY,EAAE,WAAW;AACzB,IAAA,OAAO,EAAE,CAAC;CACJ,CAAC;AAEX;AACA;AACA,MAAM,gBAAgB,GAAG,EAAE,UAAU,EAAE,qBAAqB,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC;AAC1F,MAAM,mBAAmB,GAAG,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAW,CAAC;AAE9F,MAAA,gBAAgB,GAA8B,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MACtGA,GAAC,CAAA,uBAAuB,EAAC,EAAA,KAAK,EAAE,kBAAkB,EAC9C,QAAA,EAAAC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,YAAY,EAC9B,QAAA,EAAA,CAAA,CAAC,CAAC,WAAW,IAAID,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,WAAW,EAAA,QAAA,EAAG,WAAW,EAAA,CAAO,EACzEC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,cAAc,EAAA,QAAA,EAAA,CAChC,CAAC,CAAC,KAAK,KACJD,GAAA,CAAC,uBAAuB,EAAC,EAAA,KAAK,EAAE,gBAAgB,EAC5C,QAAA,EAAAA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,MAAM,CAAC,YAAY,EAAA,QAAA,EAAG,KAAK,EAAA,CAAO,GAC5B,CAC7B,EACA,CAAC,CAAC,QAAQ,KACPA,GAAA,CAAC,uBAAuB,EAAA,EAAC,KAAK,EAAE,mBAAmB,EAAA,QAAA,EAC/CA,aAAK,SAAS,EAAE,MAAM,CAAC,eAAe,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAO,EAClC,CAAA,CAC7B,CACC,EAAA,CAAA,EACL,CAAC,CAAC,YAAY,IAAIA,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,WAAW,EAAG,QAAA,EAAA,YAAY,EAAO,CAAA,CAAA,EAAA,CACzE,EACgB,CAAA,EAC5B;AAEF,gBAAgB,CAAC,WAAW,GAAG,kBAAkB;;;;"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ChatInputFileType } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';
|
|
2
|
+
/**
|
|
3
|
+
* Тип `ChatInput.File` по MIME-типу файла: `image/*` — `image`, `video/*` — `video`, остальное — `doc`
|
|
4
|
+
*/
|
|
5
|
+
export declare const getChatInputFileType: (file: Blob) => ChatInputFileType;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import './../index.css';
|
|
2
|
+
/**
|
|
3
|
+
* Тип `ChatInput.File` по MIME-типу файла: `image/*` — `image`, `video/*` — `video`, остальное — `doc`
|
|
4
|
+
*/
|
|
5
|
+
const getChatInputFileType = (file) => {
|
|
6
|
+
if (file.type.startsWith('image/')) {
|
|
7
|
+
return 'image';
|
|
8
|
+
}
|
|
9
|
+
if (file.type.startsWith('video/')) {
|
|
10
|
+
return 'video';
|
|
11
|
+
}
|
|
12
|
+
return 'doc';
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { getChatInputFileType };
|
|
16
|
+
//# sourceMappingURL=getChatInputFileType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getChatInputFileType.js","sources":["src/public/getChatInputFileType.ts"],"sourcesContent":["import { type ChatInputFileType } from '@hh.ru/magritte-ui-chat-input/public/ChatInputFile';\n\n/**\n * Тип `ChatInput.File` по MIME-типу файла: `image/*` — `image`, `video/*` — `video`, остальное — `doc`\n */\nexport const getChatInputFileType = (file: Blob): ChatInputFileType => {\n if (file.type.startsWith('image/')) {\n return 'image';\n }\n if (file.type.startsWith('video/')) {\n return 'video';\n }\n return 'doc';\n};\n"],"names":[],"mappings":"AAEA;;AAEG;AACU,MAAA,oBAAoB,GAAG,CAAC,IAAU,KAAuB;IAClE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAChC,QAAA,OAAO,OAAO,CAAC;KAClB;IACD,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAChC,QAAA,OAAO,OAAO,CAAC;KAClB;AACD,IAAA,OAAO,KAAK,CAAC;AACjB;;;;"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
var styles = {"chat-input":"magritte-chat-input___P69oN_1-2-0","chatInput":"magritte-chat-input___P69oN_1-2-0","no-background":"magritte-no-background___eiIY1_1-2-0","noBackground":"magritte-no-background___eiIY1_1-2-0","text-input-focused":"magritte-text-input-focused___TfyLu_1-2-0","textInputFocused":"magritte-text-input-focused___TfyLu_1-2-0","content-grid":"magritte-content-grid___g03sT_1-2-0","contentGrid":"magritte-content-grid___g03sT_1-2-0","preview":"magritte-preview___baXKi_1-2-0","left":"magritte-left___7JZYp_1-2-0","central":"magritte-central___zkguj_1-2-0","right":"magritte-right___-tGcO_1-2-0","scrollbar-cell":"magritte-scrollbar-cell___--M2x_1-2-0","scrollbarCell":"magritte-scrollbar-cell___--M2x_1-2-0","text-input":"magritte-text-input___3AFO4_1-2-0","textInput":"magritte-text-input___3AFO4_1-2-0","layout-vertical":"magritte-layout-vertical___mVTr-_1-2-0","layoutVertical":"magritte-layout-vertical___mVTr-_1-2-0","has-central":"magritte-has-central___VRZik_1-2-0","hasCentral":"magritte-has-central___VRZik_1-2-0","no-left-controls":"magritte-no-left-controls___7r6yy_1-2-0","noLeftControls":"magritte-no-left-controls___7r6yy_1-2-0","no-right-controls":"magritte-no-right-controls___HBSag_1-2-0","noRightControls":"magritte-no-right-controls___HBSag_1-2-0","chips":"magritte-chips___gLao5_1-2-0","chips-container":"magritte-chips-container___-bS5O_1-2-0","chipsContainer":"magritte-chips-container___-bS5O_1-2-0","preview-block":"magritte-preview-block___iiPdS_1-2-0","previewBlock":"magritte-preview-block___iiPdS_1-2-0","preview-side":"magritte-preview-side___ymR-u_1-2-0","previewSide":"magritte-preview-side___ymR-u_1-2-0","preview-content":"magritte-preview-content___ZgyBD_1-2-0","previewContent":"magritte-preview-content___ZgyBD_1-2-0","preview-title":"magritte-preview-title___SkFeZ_1-2-0","previewTitle":"magritte-preview-title___SkFeZ_1-2-0","preview-subtitle":"magritte-preview-subtitle___58qfR_1-2-0","previewSubtitle":"magritte-preview-subtitle___58qfR_1-2-0","files-container":"magritte-files-container___zOkRK_1-2-0","filesContainer":"magritte-files-container___zOkRK_1-2-0","files":"magritte-files___j2q5K_1-2-0","file":"magritte-file___lz9Ll_1-2-0","file-card":"magritte-file-card___hn5C9_1-2-0","fileCard":"magritte-file-card___hn5C9_1-2-0","file-tile":"magritte-file-tile___OVlh3_1-2-0","fileTile":"magritte-file-tile___OVlh3_1-2-0","file-card-removable":"magritte-file-card-removable___GkxUe_1-2-0","fileCardRemovable":"magritte-file-card-removable___GkxUe_1-2-0","file-tile-placeholder":"magritte-file-tile-placeholder___yxLuR_1-2-0","fileTilePlaceholder":"magritte-file-tile-placeholder___yxLuR_1-2-0","file-tile-image":"magritte-file-tile-image___cZFgL_1-2-0","fileTileImage":"magritte-file-tile-image___cZFgL_1-2-0","file-remove":"magritte-file-remove___S0WB9_1-2-0","fileRemove":"magritte-file-remove___S0WB9_1-2-0","file-name":"magritte-file-name___L03-O_1-2-0","fileName":"magritte-file-name___L03-O_1-2-0","file-name-base":"magritte-file-name-base___ojdp6_1-2-0","fileNameBase":"magritte-file-name-base___ojdp6_1-2-0","file-name-extension":"magritte-file-name-extension___3QZtS_1-2-0","fileNameExtension":"magritte-file-name-extension___3QZtS_1-2-0","text-input-wrapper":"magritte-text-input-wrapper___TPbwC_1-2-0","textInputWrapper":"magritte-text-input-wrapper___TPbwC_1-2-0","with-top-fade":"magritte-with-top-fade___okgqo_1-2-0","withTopFade":"magritte-with-top-fade___okgqo_1-2-0","with-bottom-fade":"magritte-with-bottom-fade___82gr8_1-2-0","withBottomFade":"magritte-with-bottom-fade___82gr8_1-2-0","measure":"magritte-measure___xNKc0_1-2-0","voice-record":"magritte-voice-record___p64PV_1-2-0","voiceRecord":"magritte-voice-record___p64PV_1-2-0","voice-record-left":"magritte-voice-record-left___njEt-_1-2-0","voiceRecordLeft":"magritte-voice-record-left___njEt-_1-2-0","voice-record-right":"magritte-voice-record-right___UTv-U_1-2-0","voiceRecordRight":"magritte-voice-record-right___UTv-U_1-2-0","voice-processing":"magritte-voice-processing___C0xnX_1-2-0","voiceProcessing":"magritte-voice-processing___C0xnX_1-2-0","voice-record-indicator":"magritte-voice-record-indicator___V8ybb_1-2-0","voiceRecordIndicator":"magritte-voice-record-indicator___V8ybb_1-2-0","voice-record-indicator-bar":"magritte-voice-record-indicator-bar___jgyqz_1-2-0","voiceRecordIndicatorBar":"magritte-voice-record-indicator-bar___jgyqz_1-2-0","voice-record-indicator-wave":"magritte-voice-record-indicator-wave___4VsyE_1-2-0","voiceRecordIndicatorWave":"magritte-voice-record-indicator-wave___4VsyE_1-2-0","voice-record-indicator-has-sound":"magritte-voice-record-indicator-has-sound___67t5g_1-2-0","voiceRecordIndicatorHasSound":"magritte-voice-record-indicator-has-sound___67t5g_1-2-0","mode-container":"magritte-mode-container___nATVD_1-2-0","modeContainer":"magritte-mode-container___nATVD_1-2-0","voice-overlay":"magritte-voice-overlay___LbxAI_1-2-0","voiceOverlay":"magritte-voice-overlay___LbxAI_1-2-0"};
|
|
3
|
+
|
|
4
|
+
export { styles as s };
|
|
5
|
+
//# sourceMappingURL=styles-BHWYKmPT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles-BHWYKmPT.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/styles-CXscNVWO.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import './index.css';
|
|
2
|
-
var styles = {"chat-input":"magritte-chat-input___P69oN_1-1-19","chatInput":"magritte-chat-input___P69oN_1-1-19","no-background":"magritte-no-background___eiIY1_1-1-19","noBackground":"magritte-no-background___eiIY1_1-1-19","text-input-focused":"magritte-text-input-focused___TfyLu_1-1-19","textInputFocused":"magritte-text-input-focused___TfyLu_1-1-19","content-grid":"magritte-content-grid___g03sT_1-1-19","contentGrid":"magritte-content-grid___g03sT_1-1-19","preview":"magritte-preview___baXKi_1-1-19","left":"magritte-left___7JZYp_1-1-19","central":"magritte-central___zkguj_1-1-19","right":"magritte-right___-tGcO_1-1-19","scrollbar-cell":"magritte-scrollbar-cell___--M2x_1-1-19","scrollbarCell":"magritte-scrollbar-cell___--M2x_1-1-19","text-input":"magritte-text-input___3AFO4_1-1-19","textInput":"magritte-text-input___3AFO4_1-1-19","layout-vertical":"magritte-layout-vertical___mVTr-_1-1-19","layoutVertical":"magritte-layout-vertical___mVTr-_1-1-19","has-central":"magritte-has-central___VRZik_1-1-19","hasCentral":"magritte-has-central___VRZik_1-1-19","no-left-controls":"magritte-no-left-controls___7r6yy_1-1-19","noLeftControls":"magritte-no-left-controls___7r6yy_1-1-19","no-right-controls":"magritte-no-right-controls___HBSag_1-1-19","noRightControls":"magritte-no-right-controls___HBSag_1-1-19","chips":"magritte-chips___gLao5_1-1-19","chips-container":"magritte-chips-container___-bS5O_1-1-19","chipsContainer":"magritte-chips-container___-bS5O_1-1-19","preview-block":"magritte-preview-block___iiPdS_1-1-19","previewBlock":"magritte-preview-block___iiPdS_1-1-19","preview-side":"magritte-preview-side___ymR-u_1-1-19","previewSide":"magritte-preview-side___ymR-u_1-1-19","preview-content":"magritte-preview-content___ZgyBD_1-1-19","previewContent":"magritte-preview-content___ZgyBD_1-1-19","preview-title":"magritte-preview-title___SkFeZ_1-1-19","previewTitle":"magritte-preview-title___SkFeZ_1-1-19","preview-subtitle":"magritte-preview-subtitle___58qfR_1-1-19","previewSubtitle":"magritte-preview-subtitle___58qfR_1-1-19","text-input-wrapper":"magritte-text-input-wrapper___TPbwC_1-1-19","textInputWrapper":"magritte-text-input-wrapper___TPbwC_1-1-19","with-top-fade":"magritte-with-top-fade___okgqo_1-1-19","withTopFade":"magritte-with-top-fade___okgqo_1-1-19","with-bottom-fade":"magritte-with-bottom-fade___82gr8_1-1-19","withBottomFade":"magritte-with-bottom-fade___82gr8_1-1-19","measure":"magritte-measure___xNKc0_1-1-19","voice-record":"magritte-voice-record___p64PV_1-1-19","voiceRecord":"magritte-voice-record___p64PV_1-1-19","voice-record-left":"magritte-voice-record-left___njEt-_1-1-19","voiceRecordLeft":"magritte-voice-record-left___njEt-_1-1-19","voice-record-right":"magritte-voice-record-right___UTv-U_1-1-19","voiceRecordRight":"magritte-voice-record-right___UTv-U_1-1-19","voice-processing":"magritte-voice-processing___C0xnX_1-1-19","voiceProcessing":"magritte-voice-processing___C0xnX_1-1-19","voice-record-indicator":"magritte-voice-record-indicator___V8ybb_1-1-19","voiceRecordIndicator":"magritte-voice-record-indicator___V8ybb_1-1-19","voice-record-indicator-bar":"magritte-voice-record-indicator-bar___jgyqz_1-1-19","voiceRecordIndicatorBar":"magritte-voice-record-indicator-bar___jgyqz_1-1-19","voice-record-indicator-wave":"magritte-voice-record-indicator-wave___4VsyE_1-1-19","voiceRecordIndicatorWave":"magritte-voice-record-indicator-wave___4VsyE_1-1-19","voice-record-indicator-has-sound":"magritte-voice-record-indicator-has-sound___67t5g_1-1-19","voiceRecordIndicatorHasSound":"magritte-voice-record-indicator-has-sound___67t5g_1-1-19","mode-container":"magritte-mode-container___nATVD_1-1-19","modeContainer":"magritte-mode-container___nATVD_1-1-19","voice-overlay":"magritte-voice-overlay___LbxAI_1-1-19","voiceOverlay":"magritte-voice-overlay___LbxAI_1-1-19"};
|
|
3
|
-
|
|
4
|
-
export { styles as s };
|
|
5
|
-
//# sourceMappingURL=styles-CXscNVWO.js.map
|
package/styles-CXscNVWO.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"styles-CXscNVWO.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|