@emailmaker/filemanager 0.10.69 → 0.10.71

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.
@@ -4,21 +4,6 @@
4
4
  http://jedwatson.github.io/classnames
5
5
  */
6
6
 
7
- /*! *****************************************************************************
8
- Copyright (c) Microsoft Corporation. All rights reserved.
9
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
10
- this file except in compliance with the License. You may obtain a copy of the
11
- License at http://www.apache.org/licenses/LICENSE-2.0
12
-
13
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16
- MERCHANTABLITY OR NON-INFRINGEMENT.
17
-
18
- See the Apache Version 2.0 License for specific language governing permissions
19
- and limitations under the License.
20
- ***************************************************************************** */
21
-
22
7
  /*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
23
8
 
24
9
  /**
package/hooks/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export { useFileActions } from './useFileActions';
3
3
  export { usePixieEditor } from './usePixieEditor';
4
4
  export { useSidebarResize } from './useSidebarResize';
5
5
  export { useLastDirectory } from './useLastDirectory';
6
+ export { useControlledImageLoader } from './useControlledImageLoader';
7
+ export { useViewportMetricsSync } from './useViewportMetricsSync';
@@ -0,0 +1,6 @@
1
+ import type { NotifyEvent } from '../../types';
2
+ export declare function getNotificationDedupeKey(event: NotifyEvent): string;
3
+ /** Если то же событие уже показывали недавно — глушим видимость (silent). */
4
+ export declare function suppressIfDuplicateWithinTtl(event: NotifyEvent, ttlMs: number): void;
5
+ /** Вызывать только после фактического показа уведомления пользователю. */
6
+ export declare function recordNotificationShown(event: NotifyEvent, ttlMs: number): void;
@@ -0,0 +1,18 @@
1
+ export type ControlledImageStatus = 'idle' | 'queued' | 'loading' | 'loaded' | 'error';
2
+ export interface ControlledImageSnapshot {
3
+ status: ControlledImageStatus;
4
+ shouldLoad: boolean;
5
+ }
6
+ export interface ControlledImageLoader {
7
+ getSnapshot: (id: string, src: string) => ControlledImageSnapshot;
8
+ subscribe: (id: string, src: string, listener: (snapshot: ControlledImageSnapshot) => void) => (() => void);
9
+ setActive: (id: string, src: string, active: boolean) => void;
10
+ markLoaded: (id: string) => void;
11
+ markError: (id: string) => void;
12
+ release: (id: string) => void;
13
+ }
14
+ interface UseControlledImageLoaderOptions {
15
+ maxConcurrent?: number;
16
+ }
17
+ export declare function useControlledImageLoader({ maxConcurrent, }?: UseControlledImageLoaderOptions): ControlledImageLoader;
18
+ export {};
@@ -0,0 +1,2 @@
1
+ import { getViewportMetrics } from '../presentation/list-core/viewportMetrics';
2
+ export declare function useViewportMetricsSync<TElement extends HTMLElement>(onViewportChange: (metrics: ReturnType<typeof getViewportMetrics>) => void, deps: readonly unknown[]): import("react").MutableRefObject<TElement | null>;
package/index.d.ts CHANGED
@@ -17,7 +17,7 @@ export { FileContent } from './components/FileContent/FileContent';
17
17
  export { FileModals } from './components/FileModals/FileModals';
18
18
  export { FolderSidebar } from './components/FolderSidebar/FolderSidebar';
19
19
  export { installResizeObserverErrorHandler, uninstallResizeObserverErrorHandler } from './utils/resizeObserverHandler';
20
- export { type Folder, type File, type PathItem, type MenuItem, type FileManagerOptions, type FileManagerHookReturn, type FileManagerErrorCode, type IFileManagerApiError, type SortOptionType, } from './types';
20
+ export { type Folder, type File, type PathItem, type MenuItem, type FileManagerOptions, type FileManagerHookReturn, type FileManagerErrorCode, type IFileManagerApiError, type SortOptionType, type FileManagerItemMeta, } from './types';
21
21
  export { FileManagerApiError } from './shared/fileManagerApiError';
22
22
  export { mapHttpStatusToErrorCode } from './shared/mapHttpStatusToErrorCode';
23
23
  export { type InitPixieEditorOptions, type Options as FileManagerInitOptions, type UniversalInitOptions, } from './file-manager';
package/notification.d.ts CHANGED
@@ -143,6 +143,8 @@ interface FilesQueryParams {
143
143
  sortBy?: 'name' | 'size' | 'date' | 'type';
144
144
  sortOrder?: 'asc' | 'desc';
145
145
  itemType?: 'file' | 'folder' | 'all';
146
+ /** Человекочитаемое имя папки для UI (не отправляется на API). */
147
+ folderName?: string;
146
148
  }
147
149
 
148
150
  /**
@@ -352,6 +354,8 @@ declare namespace Notify {
352
354
  */
353
355
  export interface FetchFilesErrorPayload {
354
356
  params?: FilesQueryParams;
357
+ /** Отображаемое имя папки списка (после resolve getItem / path / кэша). */
358
+ folderName?: string | null;
355
359
  }
356
360
 
357
361
  /**
@@ -409,6 +413,11 @@ declare namespace Notify {
409
413
  * Level of the operation: 'item' for single item operations, 'batch' for batch operations.
410
414
  */
411
415
  level?: 'item' | 'batch';
416
+ /**
417
+ * Если true — применять TTL-дедупликацию одинаковых уведомлений (после interceptors).
418
+ * Для upload/мутаций обычно не задаётся или false.
419
+ */
420
+ notificationDedupe?: boolean;
412
421
  };
413
422
 
414
423
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emailmaker/filemanager",
3
- "version": "0.10.69",
3
+ "version": "0.10.71",
4
4
  "main": "./file-manager.js",
5
5
  "module": "./file-manager.esm.js",
6
6
  "types": "./index.d.ts",
@@ -3,7 +3,8 @@ import type { File as AppFile } from '../../types';
3
3
  import type { ListItemAdapter } from '../list-core/ListItemAdapter';
4
4
  import type { FileListRowModel } from './types';
5
5
  export interface FileListContext {
6
- folderFileCounts: Record<string, number>;
6
+ /** null — ошибка загрузки счётчика, показываем прочерк */
7
+ folderFileCounts: Record<string, number | null>;
7
8
  features: Record<string, boolean | undefined>;
8
9
  t: TFunction;
9
10
  /** См. Config.previewFallbackToFileUrl */
@@ -12,6 +12,7 @@ export interface FileListRowModel extends ListRowModelBase<AppFile> {
12
12
  gridInfoText: string;
13
13
  thumbnailSrc?: string;
14
14
  previewSrc?: string;
15
+ lightboxSrc?: string;
15
16
  canEdit: boolean;
16
17
  canMove: boolean;
17
18
  canCopy: boolean;
@@ -4,7 +4,7 @@ import type { RenderWindow, ViewportMetrics } from '../list-core/types';
4
4
  import type { FileListRowModel } from './types';
5
5
  interface UseFileListEngineParams {
6
6
  files: AppFile[];
7
- folderFileCounts: Record<string, number>;
7
+ folderFileCounts: Record<string, number | null>;
8
8
  features: Record<string, boolean | undefined>;
9
9
  t: TFunction;
10
10
  viewMode: 'table' | 'grid';
@@ -1,4 +1,4 @@
1
- export type RenderStrategy = 'full' | 'windowed';
1
+ export type RenderStrategy = 'full' | 'windowed' | 'positioned';
2
2
  export interface ListRowModelBase<TItem = unknown> {
3
3
  id: string;
4
4
  signature: string;
@@ -11,9 +11,25 @@ export interface WindowedRenderConfig {
11
11
  estimatedItemSize?: number;
12
12
  itemsPerLane?: number;
13
13
  }
14
+ export interface PositionedLayoutItem {
15
+ index: number;
16
+ top: number;
17
+ left: number;
18
+ width: number;
19
+ height: number;
20
+ bottom: number;
21
+ }
22
+ export interface PositionedRenderConfig {
23
+ layout: PositionedLayoutItem[];
24
+ viewportTop: number;
25
+ viewportBottom: number;
26
+ overscanPx?: number;
27
+ containerHeight: number;
28
+ }
14
29
  export interface ListEngineOptions {
15
30
  renderStrategy?: RenderStrategy;
16
31
  windowed?: WindowedRenderConfig;
32
+ positioned?: PositionedRenderConfig;
17
33
  }
18
34
  export interface ViewportMetrics {
19
35
  scrollTop: number;
@@ -28,4 +44,9 @@ export interface RenderWindow<TRowModel> {
28
44
  topOffset: number;
29
45
  bottomOffset: number;
30
46
  totalCount: number;
47
+ containerHeight?: number;
48
+ positionedItems?: Array<{
49
+ row: TRowModel;
50
+ layout: PositionedLayoutItem;
51
+ }>;
31
52
  }
@@ -0,0 +1,9 @@
1
+ import type { ListItemAdapter } from '../list-core/ListItemAdapter';
2
+ import type { MediaListRowModel } from './types';
3
+ export interface MediaListContext<TItem> {
4
+ getPreviewSrc: (item: TItem) => string | undefined;
5
+ getAltText: (item: TItem) => string;
6
+ getWidth?: (item: TItem) => number | undefined;
7
+ getHeight?: (item: TItem) => number | undefined;
8
+ }
9
+ export declare function createMediaListAdapter<TItem>(getId: (item: TItem) => string): ListItemAdapter<TItem, MediaListContext<TItem>, MediaListRowModel<TItem>>;
@@ -0,0 +1,8 @@
1
+ import type { ListRowModelBase } from '../list-core/types';
2
+ export interface MediaListRowModel<TItem> extends ListRowModelBase<TItem> {
3
+ previewSrc?: string;
4
+ altText: string;
5
+ width?: number;
6
+ height?: number;
7
+ aspectRatio: number;
8
+ }
@@ -0,0 +1,34 @@
1
+ import type { PositionedLayoutItem, ViewportMetrics, RenderWindow } from '../list-core/types';
2
+ import type { MediaListRowModel } from './types';
3
+ type MediaLayoutMode = 'masonry' | 'grid';
4
+ interface UseMediaListEngineParams<TItem> {
5
+ items: TItem[];
6
+ getId: (item: TItem) => string;
7
+ getPreviewSrc: (item: TItem) => string | undefined;
8
+ getAltText: (item: TItem) => string;
9
+ getWidth?: (item: TItem) => number | undefined;
10
+ getHeight?: (item: TItem) => number | undefined;
11
+ layoutMode?: MediaLayoutMode;
12
+ minColumnWidth?: number;
13
+ estimatedItemHeight?: number;
14
+ gap?: number;
15
+ overscanPx?: number;
16
+ prefetchThresholdPx?: number;
17
+ resolveColumnCount?: (viewportWidth: number) => number;
18
+ virtualizationThreshold?: number;
19
+ }
20
+ interface UseMediaListEngineResult<TItem> {
21
+ rowModels: MediaListRowModel<TItem>[];
22
+ renderRows: MediaListRowModel<TItem>[];
23
+ renderWindow: RenderWindow<MediaListRowModel<TItem>>;
24
+ positionedItems: Array<{
25
+ row: MediaListRowModel<TItem>;
26
+ layout: PositionedLayoutItem;
27
+ }>;
28
+ containerHeight: number;
29
+ isNearEnd: boolean;
30
+ viewportMetrics: ViewportMetrics;
31
+ handleViewportChange: (metrics: ViewportMetrics) => void;
32
+ }
33
+ export declare function useMediaListEngine<TItem>({ items, getId, getPreviewSrc, getAltText, getWidth, getHeight, layoutMode, minColumnWidth, estimatedItemHeight, gap, overscanPx, prefetchThresholdPx, resolveColumnCount, virtualizationThreshold, }: UseMediaListEngineParams<TItem>): UseMediaListEngineResult<TItem>;
34
+ export {};
package/types.d.ts CHANGED
@@ -67,6 +67,8 @@ export interface FilesQueryParams {
67
67
  sortBy?: 'name' | 'size' | 'date' | 'type';
68
68
  sortOrder?: 'asc' | 'desc';
69
69
  itemType?: 'file' | 'folder' | 'all';
70
+ /** Имя папки для уведомлений; не уходит в dataProviders.getFiles при явной передаче полей. */
71
+ folderName?: string;
70
72
  }
71
73
  export interface ApiPaginationResponse {
72
74
  page: number;
@@ -216,7 +218,18 @@ export interface UploadFilesRequest {
216
218
  items: UploadFileItemInput[];
217
219
  folderId?: string | null;
218
220
  }
221
+ /** Метаданные элемента из кэша хоста (getItem). */
222
+ export interface FileManagerItemMeta {
223
+ id: string;
224
+ name: string;
225
+ isFolder: boolean;
226
+ }
219
227
  export interface FileManagerDataProviders {
228
+ /**
229
+ * Имя/тип по id из кэша хоста (уже загруженные папки и файлы).
230
+ * Опционально; для уведомлений и подписей в UI.
231
+ */
232
+ getItem?: (id: string) => Promise<FileManagerItemMeta | null> | FileManagerItemMeta | null;
220
233
  getFileData: (fileId: string) => Promise<Blob>;
221
234
  findFileByUrl?: (url: string) => Promise<File | null>;
222
235
  getFolders?: (options?: {
@@ -378,6 +391,11 @@ export interface Config {
378
391
  disableMockServer?: boolean;
379
392
  activeTab?: string;
380
393
  showNotifications?: boolean;
394
+ /**
395
+ * TTL (мс) подавления повторных одинаковых уведомлений (type + id + data).
396
+ * 0 — выключить. По умолчанию 12 с, если не задано.
397
+ */
398
+ notificationDedupeTtlMs?: number;
381
399
  apiEndpoints?: ApiEndpoints;
382
400
  REACT_APP_GIPHY_KEY?: string;
383
401
  locale?: string;
@@ -421,7 +439,8 @@ export interface Config {
421
439
  */
422
440
  dedupeUploadNamesOnClient?: boolean;
423
441
  /**
424
- * Если нет thumbnail/thumbnailUrl, для превью в таблице/плитке использовать `file.url` (только изображения).
442
+ * Для превью в таблице/плитке разрешить fallback на `file.url` (только изображения),
443
+ * если миниатюры нет или она загрузилась с ошибкой.
425
444
  */
426
445
  previewFallbackToFileUrl?: boolean;
427
446
  /**
@@ -540,6 +559,18 @@ export interface GifItem {
540
559
  images: {
541
560
  downsized: {
542
561
  url: string;
562
+ width?: string;
563
+ height?: string;
564
+ };
565
+ fixed_width?: {
566
+ url: string;
567
+ width?: string;
568
+ height?: string;
569
+ };
570
+ fixed_width_downsampled?: {
571
+ url: string;
572
+ width?: string;
573
+ height?: string;
543
574
  };
544
575
  };
545
576
  }
@@ -556,6 +587,8 @@ export interface ImageGifProps {
556
587
  }
557
588
  export interface UnsplashImage {
558
589
  id: string;
590
+ width?: number;
591
+ height?: number;
559
592
  description: string;
560
593
  urls: {
561
594
  raw: string;
@@ -681,6 +714,7 @@ export interface FileManagerProps {
681
714
  export interface SafeImageProps {
682
715
  thumbnailSrc?: string;
683
716
  previewSrc?: string;
717
+ lightboxSrc?: string;
684
718
  alt: string;
685
719
  className?: string;
686
720
  width?: number;
@@ -1,4 +1,4 @@
1
- import { FileManagerDataProviders, File, Folder, Config, UploadFilesRequest, UploadFileResultData, BatchResult, UploadBinary } from '../types';
1
+ import { FileManagerDataProviders, File, FileManagerItemMeta, Folder, Config, UploadFilesRequest, UploadFileResultData, BatchResult, UploadBinary } from '../types';
2
2
  export declare class JSONDataProvider implements FileManagerDataProviders {
3
3
  private files;
4
4
  private folders;
@@ -12,6 +12,7 @@ export declare class JSONDataProvider implements FileManagerDataProviders {
12
12
  addFolders: (newFolders: Folder[]) => void;
13
13
  private normalizeComparableUrl;
14
14
  getFileData: (fileId: string) => Promise<Blob>;
15
+ getItem: (id: string) => Promise<FileManagerItemMeta | null>;
15
16
  findFileByUrl: (url: string) => Promise<File | null>;
16
17
  getFolders: (options?: {
17
18
  parentId?: string | null;
@@ -9,7 +9,8 @@ export interface NameProcessingOptions {
9
9
  toLowerCase?: boolean;
10
10
  }
11
11
  /**
12
- * Транслитерирует кириллицу в латиницу
12
+ * Транслитерирует кириллицу в латиницу.
13
+ * NFC: «й» в NFD — это и + combining breve; без нормализации получится «ĭ» вместо «y».
13
14
  */
14
15
  export declare function transliterateRuToEn(text: string): string;
15
16
  /**
@@ -0,0 +1,9 @@
1
+ import type { TFunction } from 'i18next';
2
+ import type { FileManagerDataProviders, Folder, PathItem } from '../types';
3
+ export declare function resolveFolderDisplayName(opts: {
4
+ folderId: string | null | undefined;
5
+ dataProviders?: FileManagerDataProviders;
6
+ folders?: Folder[];
7
+ pathHistory?: PathItem[];
8
+ t: TFunction;
9
+ }): Promise<string>;