@memori.ai/memori-react 8.38.3 → 8.38.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/components/ChatInputs/ChatInputs.js +6 -2
  3. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  4. package/dist/components/FilePreview/FilePreview.css +49 -0
  5. package/dist/components/FilePreview/FilePreview.d.ts +2 -1
  6. package/dist/components/FilePreview/FilePreview.js +11 -10
  7. package/dist/components/FilePreview/FilePreview.js.map +1 -1
  8. package/dist/components/UploadButton/UploadButton.d.ts +1 -0
  9. package/dist/components/UploadButton/UploadButton.js +21 -22
  10. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  11. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +1 -1
  12. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +76 -68
  13. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  14. package/dist/components/UploadButton/UploadImages/UploadImages.d.ts +1 -1
  15. package/dist/components/UploadButton/UploadImages/UploadImages.js +5 -2
  16. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  17. package/dist/version.d.ts +1 -1
  18. package/dist/version.js +1 -1
  19. package/esm/components/ChatInputs/ChatInputs.js +6 -2
  20. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  21. package/esm/components/FilePreview/FilePreview.css +49 -0
  22. package/esm/components/FilePreview/FilePreview.d.ts +2 -1
  23. package/esm/components/FilePreview/FilePreview.js +11 -10
  24. package/esm/components/FilePreview/FilePreview.js.map +1 -1
  25. package/esm/components/UploadButton/UploadButton.d.ts +1 -0
  26. package/esm/components/UploadButton/UploadButton.js +21 -22
  27. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  28. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +1 -1
  29. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +77 -69
  30. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  31. package/esm/components/UploadButton/UploadImages/UploadImages.d.ts +1 -1
  32. package/esm/components/UploadButton/UploadImages/UploadImages.js +5 -2
  33. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  34. package/esm/version.d.ts +1 -1
  35. package/esm/version.js +1 -1
  36. package/package.json +1 -1
  37. package/src/components/ChatInputs/ChatInputs.tsx +11 -2
  38. package/src/components/FilePreview/FilePreview.css +49 -0
  39. package/src/components/FilePreview/FilePreview.tsx +18 -4
  40. package/src/components/UploadButton/UploadButton.tsx +33 -27
  41. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +102 -101
  42. package/src/components/UploadButton/UploadImages/UploadImages.tsx +6 -4
  43. package/src/version.ts +1 -1
@@ -255,6 +255,55 @@
255
255
  line-height: 1.5;
256
256
  }
257
257
 
258
+ /* Skeleton loading card */
259
+ .memori--preview-item--skeleton {
260
+ min-width: 140px;
261
+ cursor: default;
262
+ pointer-events: none;
263
+ }
264
+
265
+ .memori--preview-item--skeleton:hover {
266
+ background-color: #f8f9fa;
267
+ transform: none;
268
+ }
269
+
270
+ .memori--skeleton-icon {
271
+ width: 20px;
272
+ height: 20px;
273
+ flex-shrink: 0;
274
+ border-radius: 4px;
275
+ animation: memori-skeleton-pulse 1.5s ease-in-out infinite;
276
+ background: linear-gradient(90deg, #e9ecef 25%, #f1f3f5 50%, #e9ecef 75%);
277
+ background-size: 200% 100%;
278
+ }
279
+
280
+ .memori--skeleton-line {
281
+ border-radius: 4px;
282
+ animation: memori-skeleton-pulse 1.5s ease-in-out infinite;
283
+ background: linear-gradient(90deg, #e9ecef 25%, #f1f3f5 50%, #e9ecef 75%);
284
+ background-size: 200% 100%;
285
+ }
286
+
287
+ .memori--skeleton-line--name {
288
+ width: 80px;
289
+ height: 12px;
290
+ margin-bottom: 6px;
291
+ }
292
+
293
+ .memori--skeleton-line--type {
294
+ width: 40px;
295
+ height: 10px;
296
+ }
297
+
298
+ @keyframes memori-skeleton-pulse {
299
+ 0% {
300
+ background-position: 200% 0;
301
+ }
302
+ 100% {
303
+ background-position: -200% 0;
304
+ }
305
+ }
306
+
258
307
  @keyframes fadeIn {
259
308
  from {
260
309
  opacity: 0;
@@ -13,7 +13,7 @@ type FilePreviewProps = {
13
13
  removeFile: (id: string, mediumID: string | undefined) => void;
14
14
  allowRemove?: boolean;
15
15
  showAnonymousRetentionNotice?: boolean;
16
- // isMessagePreview?: boolean;
16
+ uploadingCount?: number;
17
17
  };
18
18
 
19
19
  const FilePreview = ({
@@ -21,8 +21,8 @@ const FilePreview = ({
21
21
  removeFile,
22
22
  allowRemove = true,
23
23
  showAnonymousRetentionNotice = false,
24
- }: // isMessagePreview = false,
25
- FilePreviewProps) => {
24
+ uploadingCount = 0,
25
+ }: FilePreviewProps) => {
26
26
  const { t } = useTranslation();
27
27
  const [selectedFile, setSelectedFile] = useState<{
28
28
  name: string;
@@ -139,7 +139,7 @@ FilePreviewProps) => {
139
139
 
140
140
  return (
141
141
  <>
142
- {previewFiles.length > 0 && (
142
+ {(previewFiles.length > 0 || uploadingCount > 0) && (
143
143
  <div className="memori--preview-container">
144
144
  {showAnonymousRetentionNotice && (
145
145
  <small
@@ -199,6 +199,20 @@ FilePreviewProps) => {
199
199
  )}
200
200
  </div>
201
201
  ))}
202
+
203
+ {uploadingCount > 0 &&
204
+ Array.from({ length: uploadingCount }, (_, i) => (
205
+ <div
206
+ key={`skeleton-${i}`}
207
+ className="memori--preview-item memori--preview-item--document memori--preview-item--skeleton"
208
+ >
209
+ <div className="memori--skeleton-icon" />
210
+ <div className="memori--preview-file-info">
211
+ <div className="memori--skeleton-line memori--skeleton-line--name" />
212
+ <div className="memori--skeleton-line memori--skeleton-line--type" />
213
+ </div>
214
+ </div>
215
+ ))}
202
216
  </div>
203
217
  </div>
204
218
  )}
@@ -31,6 +31,8 @@ interface UploadManagerProps {
31
31
  maxDocumentsPerMessage?: number;
32
32
  /** Per-document content character limit. */
33
33
  maxDocumentContentLength?: number;
34
+ /** Called when the upload loading state changes. */
35
+ onUploadLoadingChange?: (loading: boolean, fileCount?: number) => void;
34
36
  }
35
37
 
36
38
  const UploadButton: React.FC<UploadManagerProps> = ({
@@ -44,11 +46,17 @@ const UploadButton: React.FC<UploadManagerProps> = ({
44
46
  maxTotalMessagePayload,
45
47
  maxDocumentsPerMessage = 10,
46
48
  maxDocumentContentLength = 300000,
49
+ onUploadLoadingChange,
47
50
  }) => {
48
51
  const effectivePerDocumentLimit =
49
52
  maxTotalMessagePayload ?? maxDocumentContentLength ?? 300000;
50
53
  // State
51
- const [isLoading, setIsLoading] = useState(false);
54
+ const [isDocumentLoading, setIsDocumentLoading] = useState(false);
55
+ const [isImageLoading, setIsImageLoading] = useState(false);
56
+ const isLoading = isDocumentLoading || isImageLoading;
57
+ const [docUploadingCount, setDocUploadingCount] = useState(0);
58
+ const [imgUploadingCount, setImgUploadingCount] = useState(0);
59
+ const uploadingFileCount = docUploadingCount + imgUploadingCount;
52
60
  const [errors, setErrors] = useState<
53
61
  { message: string; severity: 'error' | 'warning' | 'info' }[]
54
62
  >([]);
@@ -189,9 +197,9 @@ const UploadButton: React.FC<UploadManagerProps> = ({
189
197
  }
190
198
  }
191
199
 
192
- // Process documents
200
+ // Process documents – set loading early so skeleton shows for all entry points
193
201
  if (documentFiles.length > 0) {
194
- // Trigger document upload by creating a synthetic event
202
+ setIsDocumentLoading(true);
195
203
  const documentInput = documentRef.current?.querySelector('input[type="file"]') as HTMLInputElement;
196
204
  if (documentInput) {
197
205
  const dataTransfer = new DataTransfer();
@@ -241,7 +249,6 @@ const UploadButton: React.FC<UploadManagerProps> = ({
241
249
  const handlePaste = (e: ClipboardEvent) => {
242
250
  const clipboardData = e.clipboardData;
243
251
  if (!clipboardData) {
244
- console.log('[UploadButton] handlePaste: No clipboardData available.');
245
252
  return;
246
253
  }
247
254
 
@@ -260,12 +267,9 @@ const UploadButton: React.FC<UploadManagerProps> = ({
260
267
  // Only fall back to items if files is empty (some browsers only populate items)
261
268
  if (clipboardData.files && clipboardData.files.length > 0) {
262
269
  const clipboardFiles = Array.from(clipboardData.files);
263
- console.log(`[UploadButton] handlePaste: clipboardData.files found`, clipboardFiles);
264
270
  clipboardFiles.forEach(file => {
265
271
  if (!isDuplicate(file)) {
266
272
  files.push(file);
267
- } else {
268
- console.log(`[UploadButton] handlePaste: Duplicate file skipped from clipboardData.files:`, file);
269
273
  }
270
274
  });
271
275
  } else {
@@ -278,10 +282,7 @@ const UploadButton: React.FC<UploadManagerProps> = ({
278
282
  if (item.kind === 'file') {
279
283
  const file = item.getAsFile();
280
284
  if (file && !isDuplicate(file)) {
281
- console.log(`[UploadButton] handlePaste: Adding file from items array:`, file);
282
285
  files.push(file);
283
- } else if (file) {
284
- console.log(`[UploadButton] handlePaste: Duplicate file skipped from items array:`, file);
285
286
  }
286
287
  }
287
288
  }
@@ -289,11 +290,8 @@ const UploadButton: React.FC<UploadManagerProps> = ({
289
290
  }
290
291
 
291
292
  if (files.length > 0) {
292
- console.log(`[UploadButton] handlePaste: ${files.length} file(s) to process from paste`, files);
293
293
  e.preventDefault();
294
294
  handleUnifiedFileSelection(files);
295
- } else {
296
- console.log('[UploadButton] handlePaste: No files found in paste event.');
297
295
  }
298
296
  };
299
297
 
@@ -406,14 +404,8 @@ ${file.textAssetUrl || ''}
406
404
  };
407
405
  });
408
406
 
409
- // Keep existing images and add new documents
410
- const imageFiles = documentPreviewFiles.filter(
411
- (file: any) => file.type === 'image'
412
- );
413
-
414
- setDocumentPreviewFiles([...processedDocuments, ...imageFiles]);
415
-
416
- setIsLoading(false);
407
+ // Append new documents to existing files (images + previous documents)
408
+ setDocumentPreviewFiles((prev: any[]) => [...prev, ...processedDocuments]);
417
409
  };
418
410
 
419
411
  // Document validation and error handling
@@ -514,10 +506,24 @@ ${file.textAssetUrl || ''}
514
506
  };
515
507
 
516
508
 
517
- // Set loading state for child components
518
- const handleLoadingChange = (loading: boolean) => {
519
- setIsLoading(loading);
520
- };
509
+ const handleDocumentLoadingChange = useCallback(
510
+ (loading: boolean, fileCount?: number) => {
511
+ setIsDocumentLoading(loading);
512
+ setDocUploadingCount(loading ? (fileCount ?? 1) : 0);
513
+ },
514
+ []
515
+ );
516
+ const handleImageLoadingChange = useCallback(
517
+ (loading: boolean, fileCount?: number) => {
518
+ setIsImageLoading(loading);
519
+ setImgUploadingCount(loading ? (fileCount ?? 1) : 0);
520
+ },
521
+ []
522
+ );
523
+
524
+ useEffect(() => {
525
+ onUploadLoadingChange?.(isLoading, isLoading ? uploadingFileCount : 0);
526
+ }, [isLoading, uploadingFileCount, onUploadLoadingChange]);
521
527
 
522
528
  return (
523
529
  <div
@@ -581,7 +587,7 @@ ${file.textAssetUrl || ''}
581
587
  memoriID={memoriID}
582
588
  maxDocuments={maxDocumentsPerMessage}
583
589
  documentPreviewFiles={documentPreviewFiles}
584
- onLoadingChange={handleLoadingChange}
590
+ onLoadingChange={handleDocumentLoadingChange}
585
591
  onDocumentError={handleDocumentError}
586
592
  onValidateFile={validateDocumentFile}
587
593
  onValidatePayloadSize={validatePayloadSize}
@@ -597,7 +603,7 @@ ${file.textAssetUrl || ''}
597
603
  sessionID={sessionID}
598
604
  documentPreviewFiles={documentPreviewFiles}
599
605
  isMediaAccepted={isMediaAccepted}
600
- onLoadingChange={handleLoadingChange}
606
+ onLoadingChange={handleImageLoadingChange}
601
607
  maxImages={maxDocumentsPerMessage}
602
608
  memoriID={memoriID}
603
609
  onImageError={handleImageError}
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, useEffect } from 'react';
1
+ import React, { useState, useRef } from 'react';
2
2
  import cx from 'classnames';
3
3
  import Spin from '../../ui/Spin';
4
4
  import { DocumentIcon } from '../../icons/Document';
@@ -49,7 +49,7 @@ interface UploadDocumentsProps {
49
49
  memoriID?: string;
50
50
  maxDocuments?: number;
51
51
  documentPreviewFiles: any;
52
- onLoadingChange?: (loading: boolean) => void;
52
+ onLoadingChange?: (loading: boolean, fileCount?: number) => void;
53
53
  onDocumentError?: (error: {
54
54
  message: string;
55
55
  severity: 'error' | 'warning' | 'info';
@@ -93,12 +93,10 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
93
93
  // Refs
94
94
  const documentInputRef = useRef<HTMLInputElement>(null);
95
95
 
96
- // Update loading state in parent component
97
- useEffect(() => {
98
- if (onLoadingChange) {
99
- onLoadingChange(isLoading);
100
- }
101
- }, [isLoading, onLoadingChange]);
96
+ const setLoadingState = (loading: boolean, fileCount?: number) => {
97
+ setIsLoading(loading);
98
+ onLoadingChange?.(loading, fileCount);
99
+ };
102
100
 
103
101
  // Document upload
104
102
  const validateDocumentFile = (file: File): boolean => {
@@ -342,110 +340,113 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
342
340
  return;
343
341
  }
344
342
 
345
- setIsLoading(true);
346
-
347
- // Process each file
348
- const processedFiles: {
349
- name: string;
350
- id: string;
351
- content: string;
352
- mimeType: string;
353
- sourceUrl?: string;
354
- textAssetUrl?: string;
355
- }[] = [];
356
- let hadTruncation = false;
357
-
358
- for (const file of filesToProcess) {
359
- if (!validateDocumentFile(file)) {
360
- continue;
361
- }
343
+ setLoadingState(true, filesToProcess.length);
362
344
 
363
- const fileId = Math.random().toString(36).substr(2, 9);
345
+ try {
346
+ // Process each file
347
+ const processedFiles: {
348
+ name: string;
349
+ id: string;
350
+ content: string;
351
+ mimeType: string;
352
+ sourceUrl?: string;
353
+ textAssetUrl?: string;
354
+ }[] = [];
355
+
356
+ let activeCount = filesToProcess.length;
357
+
358
+ for (const file of filesToProcess) {
359
+ if (!validateDocumentFile(file)) {
360
+ activeCount--;
361
+ onLoadingChange?.(true, activeCount);
362
+ continue;
363
+ }
364
364
 
365
- try {
366
- const { text } = await processDocumentFile(file);
365
+ const fileId = Math.random().toString(36).substr(2, 9);
367
366
 
368
- if (text) {
369
- // Build the .txt from the FULL extracted text so the uploaded
370
- // asset always contains the complete document content.
371
- const baseName = file.name.replace(/\.[^/.]+$/, '') || file.name;
372
- const textFile = new File([text], `${baseName}.txt`, {
373
- type: 'text/plain',
374
- });
367
+ try {
368
+ const { text } = await processDocumentFile(file);
375
369
 
376
- const uploadResults = await Promise.allSettled([
377
- uploadAssetFile(file),
378
- uploadAssetFile(textFile),
379
- ]);
380
-
381
- const sourceUrl =
382
- uploadResults[0].status === 'fulfilled'
383
- ? uploadResults[0].value
384
- : undefined;
385
- const textAssetUrl =
386
- uploadResults[1].status === 'fulfilled'
387
- ? uploadResults[1].value
388
- : undefined;
389
-
390
- // Keep the document even when one of the optional links fails to upload.
391
- if (
392
- uploadResults[0].status === 'rejected' ||
393
- uploadResults[1].status === 'rejected'
394
- ) {
395
- onDocumentError?.({
396
- message: t('upload.partialAssetUploadWarning', {
397
- fileName: file.name,
398
- defaultValue:
399
- 'Some file links could not be uploaded, but the document was added anyway.',
400
- }),
401
- severity: 'warning',
370
+ if (text) {
371
+ const baseName = file.name.replace(/\.[^/.]+$/, '') || file.name;
372
+ const textFile = new File([text], `${baseName}.txt`, {
373
+ type: 'text/plain',
402
374
  });
403
- }
404
375
 
405
- // Truncate the content AFTER uploading the full-text asset,
406
- // so the message payload stays within safe limits while
407
- // the asset link preserves the complete document.
408
- let contentForMessage = text;
409
- const perDocumentLimit = maxDocumentContentLength;
410
- if (text.length > perDocumentLimit) {
411
- hadTruncation = true;
412
- contentForMessage =
413
- text.substring(0, perDocumentLimit) +
414
- '\n\n[Content truncated due to size limits]';
376
+ const uploadResults = await Promise.allSettled([
377
+ uploadAssetFile(file),
378
+ uploadAssetFile(textFile),
379
+ ]);
380
+
381
+ const sourceUrl =
382
+ uploadResults[0].status === 'fulfilled'
383
+ ? uploadResults[0].value
384
+ : undefined;
385
+ const textAssetUrl =
386
+ uploadResults[1].status === 'fulfilled'
387
+ ? uploadResults[1].value
388
+ : undefined;
389
+
390
+ if (
391
+ uploadResults[0].status === 'rejected' ||
392
+ uploadResults[1].status === 'rejected'
393
+ ) {
394
+ onDocumentError?.({
395
+ message: t('upload.partialAssetUploadWarning', {
396
+ fileName: file.name,
397
+ defaultValue:
398
+ 'Some file links could not be uploaded, but the document was added anyway.',
399
+ }),
400
+ severity: 'warning',
401
+ });
402
+ }
403
+
404
+ let contentForMessage = text;
405
+ const perDocumentLimit = maxDocumentContentLength;
406
+ if (text.length > perDocumentLimit) {
407
+ contentForMessage =
408
+ text.substring(0, perDocumentLimit) +
409
+ '\n\n[Content truncated due to size limits]';
410
+ }
411
+
412
+ processedFiles.push({
413
+ name: file.name,
414
+ id: fileId,
415
+ content: contentForMessage,
416
+ mimeType: file.type,
417
+ sourceUrl,
418
+ textAssetUrl,
419
+ });
420
+ } else {
421
+ activeCount--;
422
+ onLoadingChange?.(true, activeCount);
415
423
  }
416
-
417
- processedFiles.push({
418
- name: file.name,
419
- id: fileId,
420
- content: contentForMessage,
421
- mimeType: file.type,
422
- sourceUrl,
423
- textAssetUrl,
424
+ } catch (error) {
425
+ activeCount--;
426
+ onLoadingChange?.(true, activeCount);
427
+ console.error('File processing error:', error);
428
+ onDocumentError?.({
429
+ message: `${
430
+ error instanceof Error ? error.message : 'Unknown error'
431
+ }`,
432
+ severity: 'warning',
424
433
  });
425
434
  }
426
- } catch (error) {
427
- console.error('File processing error:', error);
428
- onDocumentError?.({
429
- message: `${
430
- error instanceof Error ? error.message : 'Unknown error'
431
- }`,
432
- severity: 'warning',
433
- });
434
435
  }
435
- }
436
436
 
437
- // Add new documents to existing ones (only those that fit within payload)
438
- if (processedFiles.length > 0) {
439
- setDocumentPreviewFiles([
440
- ...processedFiles.map(file => ({
441
- ...file,
442
- type: 'document',
443
- })),
444
- ]);
445
- }
446
- setIsLoading(false);
447
- if (documentInputRef.current) {
448
- documentInputRef.current.value = '';
437
+ if (processedFiles.length > 0) {
438
+ setDocumentPreviewFiles(
439
+ processedFiles.map(file => ({
440
+ ...file,
441
+ type: 'document',
442
+ }))
443
+ );
444
+ }
445
+ } finally {
446
+ setLoadingState(false);
447
+ if (documentInputRef.current) {
448
+ documentInputRef.current.value = '';
449
+ }
449
450
  }
450
451
  };
451
452
 
@@ -31,7 +31,7 @@ interface UploadImagesProps {
31
31
  isMediaAccepted?: boolean;
32
32
  setDocumentPreviewFiles: any;
33
33
  documentPreviewFiles: any;
34
- onLoadingChange?: (loading: boolean) => void;
34
+ onLoadingChange?: (loading: boolean, fileCount?: number) => void;
35
35
  maxImages?: number;
36
36
  memoriID?: string;
37
37
  onImageError?: (error: { message: string; severity: 'error' | 'warning' | 'info' }) => void;
@@ -60,6 +60,7 @@ const UploadImages: React.FC<UploadImagesProps> = ({
60
60
 
61
61
  // State
62
62
  const [isLoading, setIsLoading] = useState(false);
63
+ const [loadingFileCount, setLoadingFileCount] = useState(0);
63
64
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
64
65
  const [filePreview, setFilePreview] = useState<string | null>(null);
65
66
  const [imageTitle, setImageTitle] = useState('');
@@ -68,12 +69,11 @@ const UploadImages: React.FC<UploadImagesProps> = ({
68
69
  // Refs
69
70
  const imageInputRef = useRef<HTMLInputElement>(null);
70
71
 
71
- // Update loading state in parent component
72
72
  useEffect(() => {
73
73
  if (onLoadingChange) {
74
- onLoadingChange(isLoading);
74
+ onLoadingChange(isLoading, isLoading ? loadingFileCount : 0);
75
75
  }
76
- }, [isLoading, onLoadingChange]);
76
+ }, [isLoading, loadingFileCount, onLoadingChange]);
77
77
 
78
78
  // Check current total media count (images + documents)
79
79
  const currentMediaCount = documentPreviewFiles.length;
@@ -151,6 +151,7 @@ const UploadImages: React.FC<UploadImagesProps> = ({
151
151
  };
152
152
 
153
153
  const uploadMultipleImages = async (files: File[]) => {
154
+ setLoadingFileCount(files.length);
154
155
  setIsLoading(true);
155
156
 
156
157
  try {
@@ -292,6 +293,7 @@ const UploadImages: React.FC<UploadImagesProps> = ({
292
293
  const handleTitleSubmit = async () => {
293
294
  if (!selectedFile || !imageTitle.trim()) return;
294
295
 
296
+ setLoadingFileCount(1);
295
297
  setIsLoading(true);
296
298
  setShowUploadModal(false);
297
299
 
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const version = '8.38.3';
2
+ export const version = '8.38.4';