@fibery/ui-kit 1.40.3 → 1.40.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 (82) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +4 -7
  3. package/src/__snapshots__/design-system.test.ts.snap +7265 -0
  4. package/src/a11y-color.test.ts +181 -0
  5. package/src/a11y-color.ts +13 -20
  6. package/src/actions-menu/actions-menu-item.tsx +7 -7
  7. package/src/antd/ant-modal.tsx +10 -5
  8. package/src/antd/styles.ts +6 -6
  9. package/src/app-icon-with-fallback.tsx +2 -2
  10. package/src/app-icon.tsx +2 -2
  11. package/src/button/button.tsx +1 -0
  12. package/src/button/make-button-colors.ts +5 -13
  13. package/src/checkbox.tsx +2 -2
  14. package/src/color-picker/ColorPickerOrLoader.js +2 -2
  15. package/src/color-utils.test.ts +317 -0
  16. package/src/color-utils.ts +180 -0
  17. package/src/comment.tsx +3 -2
  18. package/src/context-menu/index.tsx +12 -7
  19. package/src/create-inline-theme.ts +9 -8
  20. package/src/design-system.colors.ts +760 -0
  21. package/src/design-system.test.ts +287 -7
  22. package/src/design-system.ts +146 -940
  23. package/src/dropdown-menu/index.tsx +21 -16
  24. package/src/emoji-picker/app-icon-picker.tsx +5 -5
  25. package/src/emoji-picker/emoji-picker-content-with-color.tsx +4 -4
  26. package/src/emoji-picker/icon-emoji-picker.tsx +2 -2
  27. package/src/favorites-icon.tsx +1 -1
  28. package/src/file-item/file-icon.tsx +169 -0
  29. package/src/file-item/file-menu-items.tsx +68 -0
  30. package/src/file-item/file-preview-actions.tsx +38 -0
  31. package/src/file-item/file-title.tsx +48 -0
  32. package/src/file-item/types.ts +27 -0
  33. package/src/file-item/use-register-in-image-gallery.tsx +70 -0
  34. package/src/file-item-2.tsx +35 -345
  35. package/src/file-item.tsx +6 -2
  36. package/src/hue-shift.test.ts +91 -0
  37. package/src/icons/ast/FileCounter.ts +8 -0
  38. package/src/icons/ast/FileMultiple.ts +8 -0
  39. package/src/icons/ast/ValueEdit.ts +8 -0
  40. package/src/icons/ast/index.tsx +3 -0
  41. package/src/icons/react/FileCounter.tsx +13 -0
  42. package/src/icons/react/FileMultiple.tsx +13 -0
  43. package/src/icons/react/ValueEdit.tsx +13 -0
  44. package/src/icons/react/index.tsx +3 -0
  45. package/src/icons/svg/file-counter.svg +3 -0
  46. package/src/icons/svg/file-multiple.svg +3 -0
  47. package/src/icons/svg/value-edit.svg +3 -0
  48. package/src/images-gallery/slide-buttons.tsx +4 -11
  49. package/src/lists/actions-menu-row-surface.tsx +5 -5
  50. package/src/mobile-keyboard-aware-popup.tsx +4 -3
  51. package/src/palette-generator.test.ts +566 -0
  52. package/src/palette-generator.ts +166 -0
  53. package/src/palette.ts +71 -55
  54. package/src/platform.ts +0 -3
  55. package/src/popover/index.tsx +13 -15
  56. package/src/progress.tsx +2 -2
  57. package/src/reactions/reaction-button.tsx +12 -6
  58. package/src/root-theme-provider.test.tsx +316 -0
  59. package/src/scale-generator.ts +347 -0
  60. package/src/select/components/menu-list-virtualized.tsx +7 -22
  61. package/src/select/components/menu.tsx +12 -2
  62. package/src/select/select.tsx +2 -1
  63. package/src/select/styles.ts +0 -1
  64. package/src/static-palettes.ts +146 -0
  65. package/src/thematic-color-picker.tsx +266 -0
  66. package/src/thematic-constants.tsx +27 -0
  67. package/src/thematic-controls.tsx +144 -0
  68. package/src/thematic-scales.tsx +122 -0
  69. package/src/thematic-state.ts +333 -0
  70. package/src/thematic.tsx +382 -0
  71. package/src/theme-provider.test.tsx +808 -0
  72. package/src/theme-provider.tsx +132 -69
  73. package/src/theme-settings.ts +1 -1
  74. package/src/theme-styles.ts +12 -5
  75. package/src/toast/toast-action.tsx +1 -1
  76. package/src/toggle-on-off.tsx +2 -2
  77. package/src/toggle.tsx +5 -6
  78. package/src/tooltip.tsx +13 -10
  79. package/src/type-badge.tsx +3 -3
  80. package/src/unit/styles.ts +2 -2
  81. package/src/unit/unit-with-tooltip.tsx +3 -2
  82. package/src/use-long-press.tsx +2 -2
@@ -5,6 +5,7 @@ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
5
  import {forwardRef} from "react";
6
6
  import {border, layout, space, textStyles, themeVars} from "../design-system";
7
7
  import {mobileRootSelector} from "../mobile-styles";
8
+ import {ThemeProvider} from "../theme-provider";
8
9
 
9
10
  export const Root = (dropdownMenuProps: DropdownMenuPrimitive.DropdownMenuProps) => (
10
11
  <DropdownMenuPrimitive.Root dir="ltr" modal={false} {...dropdownMenuProps} />
@@ -133,16 +134,18 @@ export const Content = forwardRef<HTMLDivElement, ContentProps>(function Dropdow
133
134
  ) {
134
135
  return (
135
136
  <Wrap if={portalled} with={DropdownMenuPrimitive.Portal} container={container}>
136
- <DropdownMenuPrimitive.Content
137
- onKeyDown={onContentKeyDown}
138
- ref={ref}
139
- className={cx(dropdownMenuContentStyles, className)}
140
- side="bottom"
141
- align="start"
142
- collisionPadding={collisionPadding}
143
- sideOffset={space.s4}
144
- {...rest}
145
- />
137
+ <ThemeProvider portal>
138
+ <DropdownMenuPrimitive.Content
139
+ onKeyDown={onContentKeyDown}
140
+ ref={ref}
141
+ className={cx(dropdownMenuContentStyles, className)}
142
+ side="bottom"
143
+ align="start"
144
+ collisionPadding={collisionPadding}
145
+ sideOffset={space.s4}
146
+ {...rest}
147
+ />
148
+ </ThemeProvider>
146
149
  </Wrap>
147
150
  );
148
151
  });
@@ -155,12 +158,14 @@ export const SubContent = forwardRef<
155
158
  >(function DropdownMenuSubContent({className, collisionPadding = space.s12, container, ...rest}, ref) {
156
159
  return (
157
160
  <DropdownMenuPrimitive.Portal container={container}>
158
- <DropdownMenuPrimitive.SubContent
159
- ref={ref}
160
- className={cx(dropdownMenuContentStyles, className)}
161
- collisionPadding={collisionPadding}
162
- {...rest}
163
- />
161
+ <ThemeProvider portal>
162
+ <DropdownMenuPrimitive.SubContent
163
+ ref={ref}
164
+ className={cx(dropdownMenuContentStyles, className)}
165
+ collisionPadding={collisionPadding}
166
+ {...rest}
167
+ />
168
+ </ThemeProvider>
164
169
  </DropdownMenuPrimitive.Portal>
165
170
  );
166
171
  });
@@ -1,7 +1,7 @@
1
1
  import {CustomEmoji, EmojiItem} from "@fibery/emoji-data";
2
2
  import {useCallback} from "react";
3
- import {cardTypeColors, getIconColor} from "../design-system";
4
- import {useThemeMode} from "../theme-provider";
3
+ import {cardTypeColors} from "../design-system";
4
+ import {useTheme} from "../theme-provider";
5
5
  import {$TSFixMe} from "../tsfixme";
6
6
  import {EmojiPickerContentWithColor, EmojiPickerContentWithColorProps} from "./emoji-picker-content-with-color";
7
7
  import {EmojiPickerContent} from "./primitives/content";
@@ -30,7 +30,7 @@ export const AppIconPicker: React.FC<AppIconPickerProps> = ({
30
30
  autoFocus = true,
31
31
  emojiSize = 20,
32
32
  }) => {
33
- const themeMode = useThemeMode();
33
+ const theme = useTheme();
34
34
 
35
35
  const renderEmoji = useCallback<NonNullable<EmojiPickerContentWithColorProps["renderEmoji"]>>(
36
36
  ({emoji}) => (
@@ -39,14 +39,14 @@ export const AppIconPicker: React.FC<AppIconPickerProps> = ({
39
39
  display: "block",
40
40
  width: emojiSize,
41
41
  height: emojiSize,
42
- fill: color ? getIconColor(themeMode, color) : undefined,
42
+ fill: color ? theme.fns.getIconColor(color) : undefined,
43
43
  }}
44
44
  viewBox="0 0 24 24"
45
45
  >
46
46
  <use href={(emoji as CustomEmoji).imageUrl} />
47
47
  </svg>
48
48
  ),
49
- [color, themeMode, emojiSize]
49
+ [color, theme, emojiSize]
50
50
  );
51
51
 
52
52
  return (
@@ -2,8 +2,8 @@ import {css} from "@linaria/core";
2
2
  import {useRef, useState} from "react";
3
3
  import {CollapsibleContent, CollapsibleRoot, CollapsibleTrigger} from "../collapsible";
4
4
  import {ColorPicker} from "../color-picker";
5
- import {getIconColor, space, themeVars} from "../design-system";
6
- import {useThemeMode} from "../theme-provider";
5
+ import {space, themeVars} from "../design-system";
6
+ import {useTheme} from "../theme-provider";
7
7
  import {Tooltip} from "../tooltip";
8
8
  import {$TSFixMe} from "../tsfixme";
9
9
  import {EmojiPickerGrid, type EmojiPickerGridHandle, EmojiPickerGridProps} from "./primitives/grid";
@@ -18,8 +18,8 @@ const colorPickerWrapperCss = css`
18
18
  type ColorPickerCollapsibleTrigger = {opened: boolean; color?: string};
19
19
 
20
20
  const ColorPickerCollapsibleTrigger: React.FC<ColorPickerCollapsibleTrigger> = ({opened, color}) => {
21
- const themeMode = useThemeMode();
22
- const iconColor = color ? getIconColor(themeMode, color) : undefined;
21
+ const theme = useTheme();
22
+ const iconColor = color ? theme.fns.getIconColor(color) : undefined;
23
23
 
24
24
  const label = opened ? "Hide color picker" : "Show color picker";
25
25
 
@@ -1,7 +1,7 @@
1
1
  import {css} from "@linaria/core";
2
2
  import {compact} from "lodash";
3
3
  import {Button} from "../button/button";
4
- import {colors, space} from "../design-system";
4
+ import {space, themeVars} from "../design-system";
5
5
  import EmojiDelete from "../icons/react/EmojiDelete";
6
6
  import {$TSFixMe} from "../tsfixme";
7
7
  import {AppIconPicker, AppIconPickerProps} from "./app-icon-picker";
@@ -11,7 +11,7 @@ import {useState} from "react";
11
11
 
12
12
  const tabNavRootStyle = css`
13
13
  padding: ${space.s4}px ${space.s12}px 0 ${space.s12}px;
14
- box-shadow: inset 0 -1px ${colors.shades.opacity5};
14
+ box-shadow: inset 0 -1px ${themeVars.shades.opacity5};
15
15
  `;
16
16
 
17
17
  type TabKey = "icons" | "emojis";
@@ -74,7 +74,7 @@ export const FavoritesIcon = ({
74
74
  onClick={onClick}
75
75
  >
76
76
  <IconButton
77
- style={checked ? makeButtonColors(theme.favoritesIconColor, "ghost") : {}}
77
+ style={checked ? makeButtonColors(theme.favoritesIconColor, "ghost", theme) : {}}
78
78
  size={size || "medium"}
79
79
  onClick={handleChange}
80
80
  color="neutral"
@@ -0,0 +1,169 @@
1
+ import FileImage from "../icons/react/FileImage";
2
+ import FileVideo from "../icons/react/FileVideo";
3
+ import FileTable from "../icons/react/FileTable";
4
+ import FileDocument from "../icons/react/FileDocument";
5
+ import FileArchive from "../icons/react/FileArchive";
6
+ import FilePresentation from "../icons/react/FilePresentation";
7
+ import AppWiki from "../icons/react/AppWiki";
8
+
9
+ export function getFileIconComponent(contentType?: string) {
10
+ if (!contentType) {
11
+ return AppWiki;
12
+ }
13
+ if (contentType.startsWith("image/")) {
14
+ return FileImage;
15
+ }
16
+ if (contentType.startsWith("video/")) {
17
+ return FileVideo;
18
+ }
19
+ if (SheetsContentTypes.includes(contentType)) {
20
+ return FileTable;
21
+ }
22
+ if (ArchiveContentTypes.includes(contentType)) {
23
+ return FileArchive;
24
+ }
25
+ if (PresentationContentTypes.includes(contentType)) {
26
+ return FilePresentation;
27
+ }
28
+ if (DocumentContentTypes.includes(contentType) || contentType.startsWith("text/")) {
29
+ return FileDocument;
30
+ }
31
+
32
+ return AppWiki;
33
+ }
34
+
35
+ export function FileIcon({contentType}: {contentType?: string}) {
36
+ const Component = getFileIconComponent(contentType);
37
+ return <Component />;
38
+ }
39
+
40
+ const ArchiveContentTypes = [
41
+ "application/zip",
42
+ "application/zip-compressed",
43
+ "application/x-zip",
44
+ "application/x-zip-compressed",
45
+ "multipart/x-zip",
46
+
47
+ "application/x-rar-compressed",
48
+ "application/vnd.rar",
49
+
50
+ "application/x-7z-compressed",
51
+
52
+ "application/gzip",
53
+ "application/x-gzip",
54
+
55
+ "application/x-tar",
56
+
57
+ "application/x-bzip",
58
+ "application/x-bzip2",
59
+ "application/x-bzip3",
60
+ "application/x-bzip4",
61
+
62
+ "application/x-xz",
63
+
64
+ "application/zstd",
65
+ "application/x-zstd",
66
+
67
+ "application/x-lzma",
68
+ "application/x-lzip",
69
+
70
+ "application/x-lzh",
71
+ "application/x-lha",
72
+
73
+ "application/x-iso9660-image",
74
+ "application/x-cd-image",
75
+
76
+ "application/x-apple-diskimage",
77
+
78
+ "application/x-arj",
79
+
80
+ "application/x-cpio",
81
+
82
+ "application/x-rpm",
83
+
84
+ "application/x-deb",
85
+ "application/vnd.debian.binary-package",
86
+
87
+ "application/x-compress",
88
+ "application/x-archive",
89
+ "application/vnd.android.package-archive",
90
+ ];
91
+
92
+ const PresentationContentTypes = [
93
+ "application/x-iwork-keynote-sffkey",
94
+ "application/vnd.ms-powerpoint",
95
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
96
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
97
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
98
+ "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
99
+ "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
100
+ "application/vnd.ms-powerpoint.template.macroEnabled.12",
101
+ "application/vnd.oasis.opendocument.presentation",
102
+ "application/vnd.oasis.opendocument.presentation-template",
103
+ "application/vnd.apple.keynote",
104
+ "application/vnd.google-apps.presentation",
105
+ "application/pdf",
106
+ "application/vnd.sun.xml.impress",
107
+ "application/vnd.stardivision.impress",
108
+ ];
109
+
110
+ const SheetsContentTypes = [
111
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
112
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
113
+ "application/vnd.ms-excel",
114
+ "application/vnd.ms-excel.sheet.macroEnabled.12",
115
+ "application/vnd.ms-excel.template.macroEnabled.12",
116
+ "application/vnd.ms-excel.addin.macroEnabled.12",
117
+ "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
118
+ "application/vnd.oasis.opendocument.spreadsheet",
119
+ "application/vnd.oasis.opendocument.spreadsheet-template",
120
+ "application/vnd.apple.numbers",
121
+ "application/vnd.google-apps.spreadsheet",
122
+ "text/csv",
123
+ "text/x-comma-separated-values",
124
+ "application/csv",
125
+ "text/tab-separated-values",
126
+ "application/vnd.lotus-1-2-3",
127
+ "application/x-123",
128
+ "application/vnd.stardivision.calc",
129
+ "application/vnd.sun.xml.calc",
130
+ "application/x-dbase",
131
+ "application/x-iwork-numbers-sffnumbers",
132
+ ];
133
+
134
+ const DocumentContentTypes = [
135
+ "application/msword",
136
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
137
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
138
+ "application/vnd.ms-word.document.macroEnabled.12",
139
+ "application/vnd.ms-word.template.macroEnabled.12",
140
+
141
+ "application/vnd.oasis.opendocument.text",
142
+ "application/vnd.oasis.opendocument.text-template",
143
+ "application/vnd.oasis.opendocument.text-master",
144
+ "application/vnd.oasis.opendocument.text-web",
145
+
146
+ "application/vnd.apple.pages",
147
+ "application/x-iwork-pages-sffpages",
148
+
149
+ "application/rtf",
150
+ "text/rtf",
151
+
152
+ "text/plain",
153
+ "text/markdown",
154
+ "text/html",
155
+
156
+ "application/vnd.google-apps.document",
157
+
158
+ "application/vnd.sun.xml.writer",
159
+ "application/vnd.sun.xml.writer.template",
160
+ "application/vnd.sun.xml.writer.global",
161
+
162
+ "application/vnd.stardivision.writer",
163
+ "application/vnd.stardivision.writer-global",
164
+
165
+ "application/x-mswrite",
166
+ "application/x-abiword",
167
+
168
+ "application/pdf",
169
+ ];
@@ -0,0 +1,68 @@
1
+ import {ReactNode} from "react";
2
+ import {useToast} from "../toast/toast-provider";
3
+ import {ActionsMenuItem, ActionsMenuSeparator} from "../actions-menu";
4
+ import Link from "../icons/react/Link";
5
+ import {copyUrlToClipboard} from "../copy-to-clipboard";
6
+ import RicheditorOpenLink from "../icons/react/RicheditorOpenLink";
7
+ import {isPhoneApp} from "../use-is-phone";
8
+ import FileDownload from "../icons/react/FileDownload";
9
+ import Pencil from "../icons/react/Pencil";
10
+ import Delete from "../icons/react/Delete";
11
+ import {UploadFileWithContent} from "./types";
12
+
13
+ export function FileMenuItems({
14
+ file,
15
+ disabled,
16
+ onDownloadClick,
17
+ onRemoveClick,
18
+ onRenameClick,
19
+ }: {
20
+ file: Pick<UploadFileWithContent, "uid" | "name" | "url" | "status">;
21
+ onDownloadClick?: () => void;
22
+ onRemoveClick?: () => void;
23
+ onRenameClick?: (data: {id: string; name: string}) => void;
24
+ disabled?: boolean;
25
+ }): ReactNode {
26
+ const toast = useToast();
27
+
28
+ return (
29
+ <>
30
+ <ActionsMenuItem
31
+ Icon={Link}
32
+ onSelect={() => {
33
+ copyUrlToClipboard({url: `${window.origin}${file.url}`, label: file.name})
34
+ .then(() => toast.success({title: "Link copied to clipboard"}))
35
+ .catch((error) => toast.error({title: "Unable to copy link to clipboard", subTitle: error.message}));
36
+ }}
37
+ >
38
+ Copy file URL
39
+ </ActionsMenuItem>
40
+ <a href={file.url} target="_blank" rel="noopener noreferrer">
41
+ <ActionsMenuItem Icon={RicheditorOpenLink}>
42
+ {isPhoneApp() ? "Open in browser" : "Open in new tab"}
43
+ </ActionsMenuItem>
44
+ </a>
45
+ {isPhoneApp() ? (
46
+ <ActionsMenuItem Icon={FileDownload} onSelect={onDownloadClick}>
47
+ Download
48
+ </ActionsMenuItem>
49
+ ) : (
50
+ <a download={file.name} href={`${file.url}?attachment`}>
51
+ <ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
52
+ </a>
53
+ )}
54
+ {onRenameClick && file.status === "done" ? (
55
+ <>
56
+ <ActionsMenuSeparator />
57
+ <ActionsMenuItem Icon={Pencil} onSelect={() => onRenameClick?.({id: file.uid, name: file.name})}>
58
+ Rename
59
+ </ActionsMenuItem>
60
+ </>
61
+ ) : null}
62
+ <ActionsMenuSeparator />
63
+ <ActionsMenuItem Icon={Delete} onSelect={onRemoveClick} dangerous disabled={disabled}>
64
+ Delete
65
+ </ActionsMenuItem>
66
+ </>
67
+ );
68
+ }
@@ -0,0 +1,38 @@
1
+ import {isPhoneApp} from "../use-is-phone";
2
+ import {ActionsMenuItem} from "../actions-menu";
3
+ import RicheditorOpenLink from "../icons/react/RicheditorOpenLink";
4
+ import FileDownload from "../icons/react/FileDownload";
5
+
6
+ export function FilePreviewActions({
7
+ url,
8
+ name,
9
+ onDownloadClick,
10
+ }: {
11
+ url: string;
12
+ name: string;
13
+ onDownloadClick?: () => void;
14
+ }) {
15
+ if (isPhoneApp()) {
16
+ return (
17
+ <>
18
+ <a href={url} target="_blank" rel="noopener noreferrer">
19
+ <ActionsMenuItem Icon={RicheditorOpenLink}>Open in browser</ActionsMenuItem>
20
+ </a>
21
+ <ActionsMenuItem Icon={FileDownload} onSelect={onDownloadClick}>
22
+ Download
23
+ </ActionsMenuItem>
24
+ </>
25
+ );
26
+ }
27
+
28
+ return (
29
+ <>
30
+ <a href={url} target="_blank" rel="noopener noreferrer">
31
+ <ActionsMenuItem Icon={RicheditorOpenLink}>Open in new tab</ActionsMenuItem>
32
+ </a>
33
+ <a download={name} href={`${url}?attachment`}>
34
+ <ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
35
+ </a>
36
+ </>
37
+ );
38
+ }
@@ -0,0 +1,48 @@
1
+ import {css, cx, LinariaClassName} from "@linaria/core";
2
+
3
+ export function FileTitle({
4
+ title,
5
+ containerCss,
6
+ maxWidth,
7
+ }: {
8
+ title: string;
9
+ containerCss?: LinariaClassName;
10
+ maxWidth?: number;
11
+ }) {
12
+ const parts = title.split(".");
13
+ const ext = parts.length > 1 ? "." + parts[parts.length - 1] : "";
14
+ const name = title.substring(0, title.length - ext.length);
15
+
16
+ return (
17
+ <div
18
+ className={cx(
19
+ css`
20
+ display: flex;
21
+ min-width: 0;
22
+ align-items: center;
23
+ `,
24
+ containerCss
25
+ )}
26
+ style={{maxWidth}}
27
+ >
28
+ <span
29
+ className={css`
30
+ white-space: nowrap;
31
+ overflow: hidden;
32
+ text-overflow: ellipsis;
33
+ /* ellipsis shows ONLY if this span overflows */
34
+ min-width: 0;
35
+ `}
36
+ >
37
+ {name}
38
+ </span>
39
+ <span
40
+ className={css`
41
+ flex: 0 0 auto;
42
+ `}
43
+ >
44
+ {ext}
45
+ </span>
46
+ </div>
47
+ );
48
+ }
@@ -0,0 +1,27 @@
1
+ export type FiberyFile = {
2
+ "fibery/id": string;
3
+ "fibery/name": string;
4
+ "fibery/rank": number;
5
+ "fibery/content-type": string;
6
+ "fibery/secret": string;
7
+ "fibery/content-length": number;
8
+ "fibery/creation-date": string;
9
+ };
10
+
11
+ export type PreviewData = {
12
+ type: "image" | "video" | "iframe";
13
+ previewSrc: string | null;
14
+ originalSrc: string;
15
+ contentType: string;
16
+ };
17
+
18
+ export type UploadFileWithContent = {
19
+ uid: string;
20
+ name: string;
21
+ url: string;
22
+ status?: string;
23
+ contentType: string;
24
+ thumbnailUrl: string | null;
25
+ downloadUrl?: string | null;
26
+ previewData: null | PreviewData;
27
+ };
@@ -0,0 +1,70 @@
1
+ import {useCallback, useEffect, useState} from "react";
2
+ import {useImagesGalleryMethods, useImagesGalleryRegistry} from "../images-gallery/images-gallery";
3
+ import {FilePreviewActions} from "./file-preview-actions";
4
+ import {PreviewData} from "./types";
5
+
6
+ export function useRegisterInImageGallery({
7
+ preview,
8
+ name,
9
+ onDownloadClick,
10
+ }: {
11
+ preview: PreviewData | null;
12
+ name: string;
13
+ onDownloadClick?: () => void;
14
+ }) {
15
+ const [zoomed, setZoomed] = useState(false);
16
+ const imagesRegistry = useImagesGalleryRegistry();
17
+ const galleryMethods = useImagesGalleryMethods();
18
+
19
+ useEffect(() => {
20
+ if (!preview) {
21
+ return;
22
+ }
23
+
24
+ imagesRegistry.set(preview.originalSrc, {
25
+ type: preview.type,
26
+ src: preview.originalSrc,
27
+ label: name,
28
+ zoomed: false,
29
+ setZoomed,
30
+ actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
31
+ });
32
+ }, [imagesRegistry, name, preview, onDownloadClick]);
33
+
34
+ useEffect(() => {
35
+ if (!preview) {
36
+ return undefined;
37
+ }
38
+
39
+ if (zoomed) {
40
+ galleryMethods.setActivated(true);
41
+ }
42
+ const imageData = imagesRegistry.get(preview.originalSrc);
43
+ if (imageData) {
44
+ imageData.zoomed = zoomed;
45
+ } else {
46
+ imagesRegistry.set(preview.originalSrc, {
47
+ type: preview.type,
48
+ src: preview.originalSrc,
49
+ label: name,
50
+ zoomed,
51
+ setZoomed,
52
+ actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
53
+ });
54
+ }
55
+
56
+ return () => {
57
+ imagesRegistry.delete(preview.originalSrc);
58
+ };
59
+ }, [galleryMethods, zoomed, preview, imagesRegistry, name, onDownloadClick]);
60
+
61
+ const openGallery = useCallback(() => {
62
+ if (preview) {
63
+ setZoomed(true);
64
+ } else {
65
+ onDownloadClick?.();
66
+ }
67
+ }, [preview, onDownloadClick]);
68
+
69
+ return {openGallery};
70
+ }