@fibery/ui-kit 1.39.0 → 1.40.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/CHANGELOG.md +12 -0
- package/package.json +3 -4
- package/src/button/select-button.tsx +11 -3
- package/src/collapsible/index.tsx +2 -2
- package/src/command-menu/index.tsx +4 -2
- package/src/copy-to-clipboard.ts +10 -0
- package/src/file-item-2.tsx +257 -150
- package/src/file-item.tsx +35 -18
- package/src/guide-link.tsx +1 -1
- package/src/html-styles.ts +2 -12
- package/src/icons/ast/FileImage.ts +1 -1
- package/src/icons/ast/Mermaid.ts +8 -0
- package/src/icons/ast/TextNoWrap.ts +8 -0
- package/src/icons/ast/TextWrap.ts +8 -0
- package/src/icons/ast/TypeId.ts +8 -0
- package/src/icons/ast/index.tsx +4 -0
- package/src/icons/react/Mermaid.tsx +13 -0
- package/src/icons/react/TextNoWrap.tsx +13 -0
- package/src/icons/react/TextWrap.tsx +13 -0
- package/src/icons/react/TypeId.tsx +13 -0
- package/src/icons/react/index.tsx +4 -0
- package/src/icons/svg/file-image.svg +2 -2
- package/src/icons/svg/mermaid.svg +3 -0
- package/src/icons/svg/text-no-wrap.svg +3 -0
- package/src/icons/svg/text-wrap.svg +3 -0
- package/src/icons/svg/type/id.svg +3 -0
- package/src/images-gallery/images-gallery-fall-through-provider.tsx +2 -1
- package/src/images-gallery/images-gallery.tsx +524 -185
- package/src/{images-gallery-2 → images-gallery}/slide-buttons.tsx +25 -13
- package/src/images-gallery/zoom.tsx +5 -94
- package/src/popover/index.tsx +5 -3
- package/src/select/components/menu-list-virtualized.tsx +123 -84
- package/src/select/components/menu.tsx +5 -3
- package/src/table.tsx +13 -10
- package/src/toggle-button/toggle-button.tsx +5 -0
- package/src/images-gallery-2/images-gallery-2.tsx +0 -522
- package/src/images-gallery-2/zoom.tsx +0 -35
package/src/file-item-2.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
import {css, cx} from "@linaria/core";
|
|
3
|
-
import {useCallback, useEffect, useState} from "react";
|
|
3
|
+
import {CSSProperties, useCallback, useEffect, useState} from "react";
|
|
4
4
|
import {ActionsMenu, ActionsMenuItem, ActionsMenuSeparator} from "./actions-menu";
|
|
5
5
|
import {ActionsButtonCompact} from "./button/actions-button-compact";
|
|
6
6
|
import {border, colors, space, themeVars, fontSize, fontWeight, lineHeight} from "./design-system";
|
|
@@ -17,10 +17,12 @@ import Link from "./icons/react/Link";
|
|
|
17
17
|
import RicheditorOpenLink from "./icons/react/RicheditorOpenLink";
|
|
18
18
|
import Spinner from "./icons/react/Spinner";
|
|
19
19
|
import AppWiki from "./icons/react/AppWiki";
|
|
20
|
-
import {
|
|
20
|
+
import {copyUrlToClipboard} from "./copy-to-clipboard";
|
|
21
21
|
import {useToast} from "./toast/toast-provider";
|
|
22
22
|
import {Icon} from "./icons/Icon";
|
|
23
23
|
import {useImagesGalleryMethods, useImagesGalleryRegistry} from "./images-gallery/images-gallery";
|
|
24
|
+
import {isPhoneApp} from "./use-is-phone";
|
|
25
|
+
import Pencil from "./icons/react/Pencil";
|
|
24
26
|
|
|
25
27
|
const fileItemStyle = css`
|
|
26
28
|
display: block;
|
|
@@ -29,13 +31,20 @@ const fileItemStyle = css`
|
|
|
29
31
|
background-size: cover;
|
|
30
32
|
text-decoration: none;
|
|
31
33
|
border-radius: ${space.s8}px;
|
|
32
|
-
border: 1px solid ${themeVars.separatorColor};
|
|
33
34
|
background-clip: padding-box;
|
|
34
35
|
&:focus {
|
|
35
36
|
text-decoration: none;
|
|
36
37
|
}
|
|
37
38
|
`;
|
|
38
39
|
|
|
40
|
+
const thumbnailStyle = css`
|
|
41
|
+
border: 1px solid ${themeVars.separatorColor};
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const iconOnlyStyle = css`
|
|
45
|
+
border: 1px solid ${themeVars.colorBorderButtonOutlineNeutralDefault};
|
|
46
|
+
`;
|
|
47
|
+
|
|
39
48
|
const overlayStyle = css`
|
|
40
49
|
width: 100%;
|
|
41
50
|
height: 100%;
|
|
@@ -63,7 +72,15 @@ const fileOverlayStyle = css`
|
|
|
63
72
|
background: transparent;
|
|
64
73
|
`;
|
|
65
74
|
|
|
75
|
+
const actionsButtonStyle = css`
|
|
76
|
+
position: absolute;
|
|
77
|
+
top: ${space.s8}px;
|
|
78
|
+
right: ${space.s8}px;
|
|
79
|
+
opacity: 0;
|
|
80
|
+
`;
|
|
81
|
+
|
|
66
82
|
export type FileItemType = {
|
|
83
|
+
uid: string;
|
|
67
84
|
name: string;
|
|
68
85
|
url: string;
|
|
69
86
|
downloadUrl?: string | null;
|
|
@@ -79,14 +96,18 @@ export type FileItemType = {
|
|
|
79
96
|
|
|
80
97
|
export type FileItemProps = {
|
|
81
98
|
data: FileItemType;
|
|
99
|
+
onDownloadClick?: () => void;
|
|
82
100
|
onRemoveClick?: (x: FileItemType) => void;
|
|
101
|
+
onRenameClick?: (x: {id: string; name: string}) => void;
|
|
83
102
|
disabled?: boolean;
|
|
84
103
|
};
|
|
85
104
|
|
|
86
105
|
export function FileItem(props: FileItemProps) {
|
|
87
|
-
const {
|
|
106
|
+
const {onDownloadClick, onRemoveClick} = props;
|
|
107
|
+
const {name, thumbnailUrl, status, previewData: preview, contentType} = props.data;
|
|
88
108
|
const isPending = status === "uploading" || status === "deleting";
|
|
89
|
-
const
|
|
109
|
+
const [isThumbnailLoadFailed, setIsThumbnailLoadFailed] = useState(false);
|
|
110
|
+
const isBackgroundReady = !isThumbnailLoadFailed && Boolean(thumbnailUrl && !isPending);
|
|
90
111
|
const [isActionsOpened, setIsActionsOpened] = useState(false);
|
|
91
112
|
|
|
92
113
|
const showFileIcon = !isPending && !isBackgroundReady;
|
|
@@ -103,11 +124,12 @@ export function FileItem(props: FileItemProps) {
|
|
|
103
124
|
imagesRegistry.set(preview.originalSrc, {
|
|
104
125
|
type: preview.type,
|
|
105
126
|
src: preview.originalSrc,
|
|
127
|
+
label: name,
|
|
106
128
|
zoomed: false,
|
|
107
129
|
setZoomed,
|
|
108
|
-
actions: <FilePreviewActions url={preview.originalSrc} name={name} />,
|
|
130
|
+
actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
|
|
109
131
|
});
|
|
110
|
-
}, [imagesRegistry, name, preview]);
|
|
132
|
+
}, [imagesRegistry, name, preview, onDownloadClick]);
|
|
111
133
|
|
|
112
134
|
useEffect(() => {
|
|
113
135
|
if (!preview) {
|
|
@@ -124,79 +146,86 @@ export function FileItem(props: FileItemProps) {
|
|
|
124
146
|
imagesRegistry.set(preview.originalSrc, {
|
|
125
147
|
type: preview.type,
|
|
126
148
|
src: preview.originalSrc,
|
|
149
|
+
label: name,
|
|
127
150
|
zoomed,
|
|
128
151
|
setZoomed,
|
|
129
|
-
actions: <FilePreviewActions url={preview.originalSrc} name={name} />,
|
|
152
|
+
actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
|
|
130
153
|
});
|
|
131
154
|
}
|
|
132
|
-
}, [galleryMethods, zoomed, preview, imagesRegistry, name]);
|
|
155
|
+
}, [galleryMethods, zoomed, preview, imagesRegistry, name, onDownloadClick]);
|
|
133
156
|
|
|
134
157
|
const onContainerClick = useCallback(() => {
|
|
135
158
|
if (preview) {
|
|
136
159
|
setZoomed(true);
|
|
137
160
|
} else {
|
|
138
|
-
|
|
161
|
+
onDownloadClick?.();
|
|
139
162
|
}
|
|
140
|
-
}, [
|
|
163
|
+
}, [preview, onDownloadClick]);
|
|
141
164
|
|
|
142
165
|
return (
|
|
143
|
-
|
|
144
|
-
className={cx(
|
|
145
|
-
css`
|
|
146
|
-
flex: 1 0 0;
|
|
147
|
-
height: 100%;
|
|
148
|
-
`,
|
|
149
|
-
isBackgroundReady &&
|
|
150
|
-
css`
|
|
151
|
-
&:hover .${overlayStyle} {
|
|
152
|
-
opacity: 1;
|
|
153
|
-
background-position: 0 0;
|
|
154
|
-
color: ${themeVars.whiteColor};
|
|
155
|
-
background-color: rgba(0, 0, 0, 0.6);
|
|
156
|
-
}
|
|
157
|
-
`,
|
|
158
|
-
isBackgroundReady &&
|
|
159
|
-
isActionsOpened &&
|
|
160
|
-
css`
|
|
161
|
-
.${overlayStyle} {
|
|
162
|
-
opacity: 1;
|
|
163
|
-
background-position: 0 0;
|
|
164
|
-
color: ${themeVars.whiteColor};
|
|
165
|
-
background-color: rgba(0, 0, 0, 0.6);
|
|
166
|
-
}
|
|
167
|
-
`
|
|
168
|
-
)}
|
|
169
|
-
>
|
|
166
|
+
<>
|
|
170
167
|
<div
|
|
171
|
-
style={isBackgroundReady ? {backgroundImage: `url(${thumbnailUrl})`} : {}}
|
|
172
|
-
onClick={onContainerClick}
|
|
173
168
|
className={cx(
|
|
174
169
|
css`
|
|
175
|
-
flex
|
|
170
|
+
flex: 1 0 0;
|
|
171
|
+
height: 100%;
|
|
176
172
|
`,
|
|
177
|
-
|
|
178
|
-
isPending &&
|
|
173
|
+
isBackgroundReady &&
|
|
179
174
|
css`
|
|
180
|
-
|
|
175
|
+
&:hover .${overlayStyle} {
|
|
176
|
+
opacity: 1;
|
|
177
|
+
background-position: 0 0;
|
|
178
|
+
color: ${themeVars.whiteColor};
|
|
179
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
180
|
+
}
|
|
181
|
+
`,
|
|
182
|
+
isBackgroundReady &&
|
|
183
|
+
isActionsOpened &&
|
|
184
|
+
css`
|
|
185
|
+
.${overlayStyle} {
|
|
186
|
+
opacity: 1;
|
|
187
|
+
background-position: 0 0;
|
|
188
|
+
color: ${themeVars.whiteColor};
|
|
189
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
190
|
+
}
|
|
191
|
+
`,
|
|
192
|
+
!isBackgroundReady &&
|
|
193
|
+
css`
|
|
194
|
+
&:hover .${overlayStyle} {
|
|
195
|
+
background-color: ${themeVars.colorBgMenuItemHover};
|
|
196
|
+
}
|
|
197
|
+
&:hover .${actionsButtonStyle} {
|
|
198
|
+
opacity: 1;
|
|
199
|
+
}
|
|
200
|
+
`,
|
|
201
|
+
!isBackgroundReady &&
|
|
202
|
+
isActionsOpened &&
|
|
203
|
+
css`
|
|
204
|
+
.${overlayStyle} {
|
|
205
|
+
background-color: ${themeVars.colorBgMenuItemHover};
|
|
206
|
+
}
|
|
207
|
+
.${actionsButtonStyle} {
|
|
208
|
+
opacity: 1;
|
|
209
|
+
}
|
|
181
210
|
`
|
|
182
211
|
)}
|
|
183
212
|
>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
213
|
+
<div
|
|
214
|
+
style={isBackgroundReady ? {backgroundImage: `url(${thumbnailUrl})`} : {}}
|
|
215
|
+
onClick={onContainerClick}
|
|
216
|
+
className={cx(
|
|
217
|
+
css`
|
|
218
|
+
flex-shrink: 0;
|
|
219
|
+
`,
|
|
220
|
+
fileItemStyle,
|
|
221
|
+
showFileIcon ? iconOnlyStyle : thumbnailStyle,
|
|
222
|
+
isPending &&
|
|
223
|
+
css`
|
|
224
|
+
${{backgroundColor: themeVars.entityCardSelectedColor}}
|
|
225
|
+
`
|
|
226
|
+
)}
|
|
227
|
+
>
|
|
228
|
+
{isPending && (
|
|
200
229
|
<div
|
|
201
230
|
className={css`
|
|
202
231
|
display: flex;
|
|
@@ -205,99 +234,122 @@ export function FileItem(props: FileItemProps) {
|
|
|
205
234
|
align-items: center; /* centers horizontally */
|
|
206
235
|
height: 100%;
|
|
207
236
|
width: 100%;
|
|
208
|
-
padding-top: ${space.s1}px;
|
|
209
|
-
gap: ${space.s2}px;
|
|
210
237
|
`}
|
|
211
238
|
>
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
239
|
+
<Spinner />
|
|
240
|
+
</div>
|
|
241
|
+
)}
|
|
242
|
+
{showFileIcon && (
|
|
243
|
+
<div className={cx(overlayStyle, fileOverlayStyle)}>
|
|
215
244
|
<div
|
|
216
245
|
className={css`
|
|
217
|
-
align-content: center;
|
|
218
|
-
|
|
219
246
|
display: flex;
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
247
|
+
flex-direction: column;
|
|
248
|
+
justify-content: center; /* centers vertically */
|
|
249
|
+
align-items: center; /* centers horizontally */
|
|
250
|
+
height: 100%;
|
|
251
|
+
width: 100%;
|
|
252
|
+
padding-top: ${space.s1}px;
|
|
253
|
+
gap: ${space.s2}px;
|
|
226
254
|
`}
|
|
227
255
|
>
|
|
228
|
-
<
|
|
229
|
-
|
|
256
|
+
<Icon containerSize={40} iconSize={40}>
|
|
257
|
+
<FileIcon contentType={contentType} />
|
|
258
|
+
</Icon>
|
|
259
|
+
<div
|
|
230
260
|
className={css`
|
|
231
|
-
-
|
|
232
|
-
|
|
233
|
-
|
|
261
|
+
align-content: center;
|
|
262
|
+
|
|
263
|
+
display: flex;
|
|
264
|
+
align-items: center;
|
|
265
|
+
gap: 10px;
|
|
266
|
+
flex-shrink: 0;
|
|
267
|
+
color: ${themeVars.colorTextMenuItem};
|
|
234
268
|
text-overflow: ellipsis;
|
|
269
|
+
overflow: hidden;
|
|
235
270
|
`}
|
|
236
|
-
|
|
271
|
+
>
|
|
272
|
+
<FileTitle
|
|
273
|
+
title={name}
|
|
274
|
+
className={css`
|
|
275
|
+
-webkit-line-clamp: 1;
|
|
276
|
+
-webkit-box-orient: vertical;
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
text-overflow: ellipsis;
|
|
279
|
+
`}
|
|
280
|
+
/>
|
|
281
|
+
</div>
|
|
237
282
|
</div>
|
|
238
|
-
|
|
239
|
-
<div
|
|
240
|
-
className={css`
|
|
241
|
-
position: absolute;
|
|
242
|
-
top: ${space.s8}px;
|
|
243
|
-
right: ${space.s8}px;
|
|
244
|
-
`}
|
|
245
|
-
>
|
|
246
|
-
<FileActionsMenu
|
|
247
|
-
setIsActionsOpened={setIsActionsOpened}
|
|
248
|
-
data={props.data}
|
|
249
|
-
disabled={props.disabled}
|
|
250
|
-
isBackgroundReady={isBackgroundReady}
|
|
251
|
-
onRemoveClick={props.onRemoveClick}
|
|
252
|
-
/>
|
|
253
|
-
</div>
|
|
254
|
-
</div>
|
|
255
|
-
)}
|
|
256
|
-
{!isPending && !showFileIcon && (
|
|
257
|
-
<div className={cx(overlayStyle, isBackgroundReady ? imageOverlayStyle : fileOverlayStyle)}>
|
|
258
|
-
<div
|
|
259
|
-
className={css`
|
|
260
|
-
position: relative;
|
|
261
|
-
display: flex;
|
|
262
|
-
flex-direction: column;
|
|
263
|
-
justify-content: space-between; /* Top + bottom placement */
|
|
264
|
-
width: 100%;
|
|
265
|
-
height: 100%;
|
|
266
|
-
overflow: hidden;
|
|
267
|
-
box-sizing: border-box;
|
|
268
|
-
gap: ${space.s8}px;
|
|
269
|
-
`}
|
|
270
|
-
>
|
|
271
|
-
<div
|
|
272
|
-
className={css`
|
|
273
|
-
align-self: flex-end;
|
|
274
|
-
`}
|
|
275
|
-
>
|
|
283
|
+
<div className={actionsButtonStyle}>
|
|
276
284
|
<FileActionsMenu
|
|
277
285
|
setIsActionsOpened={setIsActionsOpened}
|
|
278
286
|
data={props.data}
|
|
279
287
|
disabled={props.disabled}
|
|
280
|
-
|
|
281
|
-
onRemoveClick={
|
|
288
|
+
onDownloadClick={onDownloadClick}
|
|
289
|
+
onRemoveClick={onRemoveClick}
|
|
290
|
+
onRenameClick={props.onRenameClick}
|
|
282
291
|
/>
|
|
283
292
|
</div>
|
|
293
|
+
</div>
|
|
294
|
+
)}
|
|
295
|
+
{!isPending && !showFileIcon && (
|
|
296
|
+
<div className={cx(overlayStyle, isBackgroundReady ? imageOverlayStyle : fileOverlayStyle)}>
|
|
284
297
|
<div
|
|
285
298
|
className={css`
|
|
299
|
+
position: relative;
|
|
286
300
|
display: flex;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
301
|
+
flex-direction: column;
|
|
302
|
+
justify-content: space-between; /* Top + bottom placement */
|
|
303
|
+
width: 100%;
|
|
304
|
+
height: 100%;
|
|
305
|
+
overflow: hidden;
|
|
291
306
|
box-sizing: border-box;
|
|
307
|
+
gap: ${space.s8}px;
|
|
292
308
|
`}
|
|
293
309
|
>
|
|
294
|
-
<
|
|
310
|
+
<div
|
|
311
|
+
className={css`
|
|
312
|
+
align-self: flex-end;
|
|
313
|
+
`}
|
|
314
|
+
>
|
|
315
|
+
<FileActionsMenu
|
|
316
|
+
setIsActionsOpened={setIsActionsOpened}
|
|
317
|
+
data={props.data}
|
|
318
|
+
disabled={props.disabled}
|
|
319
|
+
actionsButtonStyle={
|
|
320
|
+
isBackgroundReady ? makeButtonColors(colors.inversedTextColor, "ghost") : undefined
|
|
321
|
+
}
|
|
322
|
+
onDownloadClick={onDownloadClick}
|
|
323
|
+
onRemoveClick={props.onRemoveClick}
|
|
324
|
+
onRenameClick={props.onRenameClick}
|
|
325
|
+
/>
|
|
326
|
+
</div>
|
|
327
|
+
<div
|
|
328
|
+
className={css`
|
|
329
|
+
display: flex;
|
|
330
|
+
align-self: flex-start;
|
|
331
|
+
align-items: flex-end;
|
|
332
|
+
text-overflow: ellipsis;
|
|
333
|
+
//overflow: hidden;
|
|
334
|
+
box-sizing: border-box;
|
|
335
|
+
`}
|
|
336
|
+
>
|
|
337
|
+
<FileTitle title={name} />
|
|
338
|
+
</div>
|
|
295
339
|
</div>
|
|
296
340
|
</div>
|
|
297
|
-
|
|
298
|
-
|
|
341
|
+
)}
|
|
342
|
+
</div>
|
|
343
|
+
{thumbnailUrl ? (
|
|
344
|
+
<img
|
|
345
|
+
style={{display: "none"}}
|
|
346
|
+
onError={() => setIsThumbnailLoadFailed(true)}
|
|
347
|
+
src={thumbnailUrl}
|
|
348
|
+
alt="invisible"
|
|
349
|
+
/>
|
|
350
|
+
) : null}
|
|
299
351
|
</div>
|
|
300
|
-
|
|
352
|
+
</>
|
|
301
353
|
);
|
|
302
354
|
}
|
|
303
355
|
|
|
@@ -305,14 +357,18 @@ function FileActionsMenu({
|
|
|
305
357
|
data,
|
|
306
358
|
disabled,
|
|
307
359
|
setIsActionsOpened,
|
|
360
|
+
onDownloadClick,
|
|
308
361
|
onRemoveClick,
|
|
309
|
-
|
|
362
|
+
onRenameClick,
|
|
363
|
+
actionsButtonStyle,
|
|
310
364
|
}: {
|
|
311
365
|
data: FileItemType;
|
|
366
|
+
onDownloadClick?: () => void;
|
|
312
367
|
onRemoveClick?: (data: FileItemType) => void;
|
|
368
|
+
onRenameClick?: (data: {id: string; name: string}) => void;
|
|
313
369
|
disabled?: boolean;
|
|
314
370
|
setIsActionsOpened: (val: boolean) => void;
|
|
315
|
-
|
|
371
|
+
actionsButtonStyle?: CSSProperties;
|
|
316
372
|
}) {
|
|
317
373
|
const toast = useToast();
|
|
318
374
|
|
|
@@ -324,14 +380,14 @@ function FileActionsMenu({
|
|
|
324
380
|
className={css`
|
|
325
381
|
z-index: 1;
|
|
326
382
|
`}
|
|
327
|
-
style={
|
|
383
|
+
style={actionsButtonStyle}
|
|
328
384
|
/>
|
|
329
385
|
}
|
|
330
386
|
>
|
|
331
387
|
<ActionsMenuItem
|
|
332
388
|
Icon={Link}
|
|
333
389
|
onSelect={() => {
|
|
334
|
-
|
|
390
|
+
copyUrlToClipboard({url: `${window.origin}${data.url}`, label: data.name})
|
|
335
391
|
.then(() => toast.success({title: "Link copied to clipboard"}))
|
|
336
392
|
.catch((error) => toast.error({title: "Unable to copy link to clipboard", subTitle: error.message}));
|
|
337
393
|
}}
|
|
@@ -339,11 +395,27 @@ function FileActionsMenu({
|
|
|
339
395
|
Copy file URL
|
|
340
396
|
</ActionsMenuItem>
|
|
341
397
|
<a href={data.url} target="_blank" rel="noopener noreferrer">
|
|
342
|
-
<ActionsMenuItem Icon={RicheditorOpenLink}>
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
<ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
|
|
398
|
+
<ActionsMenuItem Icon={RicheditorOpenLink}>
|
|
399
|
+
{isPhoneApp() ? "Open in browser" : "Open in new tab"}
|
|
400
|
+
</ActionsMenuItem>
|
|
346
401
|
</a>
|
|
402
|
+
{isPhoneApp() ? (
|
|
403
|
+
<ActionsMenuItem Icon={FileDownload} onSelect={onDownloadClick}>
|
|
404
|
+
Download
|
|
405
|
+
</ActionsMenuItem>
|
|
406
|
+
) : (
|
|
407
|
+
<a download={data.name} href={`${data.url}?attachment`}>
|
|
408
|
+
<ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
|
|
409
|
+
</a>
|
|
410
|
+
)}
|
|
411
|
+
{onRenameClick && data.status === "done" ? (
|
|
412
|
+
<>
|
|
413
|
+
<ActionsMenuSeparator />
|
|
414
|
+
<ActionsMenuItem Icon={Pencil} onSelect={() => onRenameClick?.({id: data.uid, name: data.name})}>
|
|
415
|
+
Rename
|
|
416
|
+
</ActionsMenuItem>
|
|
417
|
+
</>
|
|
418
|
+
) : null}
|
|
347
419
|
<ActionsMenuSeparator />
|
|
348
420
|
<ActionsMenuItem Icon={Delete} onSelect={() => onRemoveClick?.(data)} dangerous disabled={disabled}>
|
|
349
421
|
Delete
|
|
@@ -353,6 +425,10 @@ function FileActionsMenu({
|
|
|
353
425
|
}
|
|
354
426
|
|
|
355
427
|
function FileTitle({title, className}: {title: string; className?: string}) {
|
|
428
|
+
const parts = title.split(".");
|
|
429
|
+
const ext = parts.length > 1 ? "." + parts[parts.length - 1] : "";
|
|
430
|
+
const name = title.substring(0, title.length - ext.length);
|
|
431
|
+
|
|
356
432
|
return (
|
|
357
433
|
<div
|
|
358
434
|
className={cx(
|
|
@@ -368,7 +444,7 @@ function FileTitle({title, className}: {title: string; className?: string}) {
|
|
|
368
444
|
overflow: hidden;
|
|
369
445
|
font-size: ${fontSize.mini}px;
|
|
370
446
|
font-weight: ${fontWeight.medium};
|
|
371
|
-
line-height: ${lineHeight.
|
|
447
|
+
line-height: ${lineHeight.heading};
|
|
372
448
|
text-transform: none;
|
|
373
449
|
text-overflow: ellipsis;
|
|
374
450
|
-webkit-line-clamp: 1;
|
|
@@ -382,12 +458,51 @@ function FileTitle({title, className}: {title: string; className?: string}) {
|
|
|
382
458
|
className
|
|
383
459
|
)}
|
|
384
460
|
>
|
|
385
|
-
|
|
461
|
+
<div
|
|
462
|
+
className={css`
|
|
463
|
+
display: flex;
|
|
464
|
+
min-width: 0;
|
|
465
|
+
align-items: center;
|
|
466
|
+
max-width: 120px;
|
|
467
|
+
`}
|
|
468
|
+
>
|
|
469
|
+
<span
|
|
470
|
+
className={css`
|
|
471
|
+
white-space: nowrap;
|
|
472
|
+
overflow: hidden;
|
|
473
|
+
text-overflow: ellipsis;
|
|
474
|
+
/* ellipsis shows ONLY if this span overflows */
|
|
475
|
+
min-width: 0;
|
|
476
|
+
`}
|
|
477
|
+
>
|
|
478
|
+
{name}
|
|
479
|
+
</span>
|
|
480
|
+
<span
|
|
481
|
+
className={css`
|
|
482
|
+
flex: 0 0 auto;
|
|
483
|
+
`}
|
|
484
|
+
>
|
|
485
|
+
{ext}
|
|
486
|
+
</span>
|
|
487
|
+
</div>
|
|
386
488
|
</div>
|
|
387
489
|
);
|
|
388
490
|
}
|
|
389
491
|
|
|
390
|
-
function FilePreviewActions({url, name}: {url: string; name: string}) {
|
|
492
|
+
function FilePreviewActions({url, name, onDownloadClick}: {url: string; name: string; onDownloadClick?: () => void}) {
|
|
493
|
+
if (isPhoneApp()) {
|
|
494
|
+
return (
|
|
495
|
+
<>
|
|
496
|
+
<a href={url} target="_blank" rel="noopener noreferrer">
|
|
497
|
+
<ActionsMenuItem Icon={RicheditorOpenLink}>Open in browser</ActionsMenuItem>
|
|
498
|
+
</a>
|
|
499
|
+
<ActionsMenuItem Icon={FileDownload} onSelect={onDownloadClick}>
|
|
500
|
+
Download
|
|
501
|
+
</ActionsMenuItem>
|
|
502
|
+
</>
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
391
506
|
return (
|
|
392
507
|
<>
|
|
393
508
|
<a href={url} target="_blank" rel="noopener noreferrer">
|
|
@@ -400,18 +515,10 @@ function FilePreviewActions({url, name}: {url: string; name: string}) {
|
|
|
400
515
|
);
|
|
401
516
|
}
|
|
402
517
|
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
a.style.display = "none";
|
|
408
|
-
|
|
409
|
-
document.body.appendChild(a);
|
|
410
|
-
a.click();
|
|
411
|
-
document.body.removeChild(a);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function FileIcon({contentType}: {contentType: string}) {
|
|
518
|
+
function FileIcon({contentType}: {contentType?: string}) {
|
|
519
|
+
if (!contentType) {
|
|
520
|
+
return <AppWiki />;
|
|
521
|
+
}
|
|
415
522
|
if (contentType.startsWith("image/")) {
|
|
416
523
|
return <FileImage />;
|
|
417
524
|
}
|