@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.
- package/CHANGELOG.md +8 -0
- package/package.json +4 -7
- package/src/__snapshots__/design-system.test.ts.snap +7265 -0
- package/src/a11y-color.test.ts +181 -0
- package/src/a11y-color.ts +13 -20
- package/src/actions-menu/actions-menu-item.tsx +7 -7
- package/src/antd/ant-modal.tsx +10 -5
- package/src/antd/styles.ts +6 -6
- package/src/app-icon-with-fallback.tsx +2 -2
- package/src/app-icon.tsx +2 -2
- package/src/button/button.tsx +1 -0
- package/src/button/make-button-colors.ts +5 -13
- package/src/checkbox.tsx +2 -2
- package/src/color-picker/ColorPickerOrLoader.js +2 -2
- package/src/color-utils.test.ts +317 -0
- package/src/color-utils.ts +180 -0
- package/src/comment.tsx +3 -2
- package/src/context-menu/index.tsx +12 -7
- package/src/create-inline-theme.ts +9 -8
- package/src/design-system.colors.ts +760 -0
- package/src/design-system.test.ts +287 -7
- package/src/design-system.ts +146 -940
- package/src/dropdown-menu/index.tsx +21 -16
- package/src/emoji-picker/app-icon-picker.tsx +5 -5
- package/src/emoji-picker/emoji-picker-content-with-color.tsx +4 -4
- package/src/emoji-picker/icon-emoji-picker.tsx +2 -2
- package/src/favorites-icon.tsx +1 -1
- package/src/file-item/file-icon.tsx +169 -0
- package/src/file-item/file-menu-items.tsx +68 -0
- package/src/file-item/file-preview-actions.tsx +38 -0
- package/src/file-item/file-title.tsx +48 -0
- package/src/file-item/types.ts +27 -0
- package/src/file-item/use-register-in-image-gallery.tsx +70 -0
- package/src/file-item-2.tsx +35 -345
- package/src/file-item.tsx +6 -2
- package/src/hue-shift.test.ts +91 -0
- package/src/icons/ast/FileCounter.ts +8 -0
- package/src/icons/ast/FileMultiple.ts +8 -0
- package/src/icons/ast/ValueEdit.ts +8 -0
- package/src/icons/ast/index.tsx +3 -0
- package/src/icons/react/FileCounter.tsx +13 -0
- package/src/icons/react/FileMultiple.tsx +13 -0
- package/src/icons/react/ValueEdit.tsx +13 -0
- package/src/icons/react/index.tsx +3 -0
- package/src/icons/svg/file-counter.svg +3 -0
- package/src/icons/svg/file-multiple.svg +3 -0
- package/src/icons/svg/value-edit.svg +3 -0
- package/src/images-gallery/slide-buttons.tsx +4 -11
- package/src/lists/actions-menu-row-surface.tsx +5 -5
- package/src/mobile-keyboard-aware-popup.tsx +4 -3
- package/src/palette-generator.test.ts +566 -0
- package/src/palette-generator.ts +166 -0
- package/src/palette.ts +71 -55
- package/src/platform.ts +0 -3
- package/src/popover/index.tsx +13 -15
- package/src/progress.tsx +2 -2
- package/src/reactions/reaction-button.tsx +12 -6
- package/src/root-theme-provider.test.tsx +316 -0
- package/src/scale-generator.ts +347 -0
- package/src/select/components/menu-list-virtualized.tsx +7 -22
- package/src/select/components/menu.tsx +12 -2
- package/src/select/select.tsx +2 -1
- package/src/select/styles.ts +0 -1
- package/src/static-palettes.ts +146 -0
- package/src/thematic-color-picker.tsx +266 -0
- package/src/thematic-constants.tsx +27 -0
- package/src/thematic-controls.tsx +144 -0
- package/src/thematic-scales.tsx +122 -0
- package/src/thematic-state.ts +333 -0
- package/src/thematic.tsx +382 -0
- package/src/theme-provider.test.tsx +808 -0
- package/src/theme-provider.tsx +132 -69
- package/src/theme-settings.ts +1 -1
- package/src/theme-styles.ts +12 -5
- package/src/toast/toast-action.tsx +1 -1
- package/src/toggle-on-off.tsx +2 -2
- package/src/toggle.tsx +5 -6
- package/src/tooltip.tsx +13 -10
- package/src/type-badge.tsx +3 -3
- package/src/unit/styles.ts +2 -2
- package/src/unit/unit-with-tooltip.tsx +3 -2
- package/src/use-long-press.tsx +2 -2
package/src/file-item-2.tsx
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
|
-
/* eslint-disable max-lines */
|
|
2
1
|
import {css, cx} from "@linaria/core";
|
|
3
|
-
import {CSSProperties,
|
|
4
|
-
import {ActionsMenu
|
|
2
|
+
import {CSSProperties, useState} from "react";
|
|
3
|
+
import {ActionsMenu} from "./actions-menu";
|
|
5
4
|
import {ActionsButtonCompact} from "./button/actions-button-compact";
|
|
6
|
-
import {border,
|
|
5
|
+
import {border, fontSize, fontWeight, lineHeight, space, themeVars} from "./design-system";
|
|
7
6
|
import {makeButtonColors} from "./button/make-button-colors";
|
|
8
|
-
import
|
|
9
|
-
import FileDownload from "./icons/react/FileDownload";
|
|
10
|
-
import FileImage from "./icons/react/FileImage";
|
|
11
|
-
import FileVideo from "./icons/react/FileVideo";
|
|
12
|
-
import FileTable from "./icons/react/FileTable";
|
|
13
|
-
import FileDocument from "./icons/react/FileDocument";
|
|
14
|
-
import FileArchive from "./icons/react/FileArchive";
|
|
15
|
-
import FilePresentation from "./icons/react/FilePresentation";
|
|
16
|
-
import Link from "./icons/react/Link";
|
|
17
|
-
import RicheditorOpenLink from "./icons/react/RicheditorOpenLink";
|
|
7
|
+
import {useTheme} from "./theme-provider";
|
|
18
8
|
import Spinner from "./icons/react/Spinner";
|
|
19
|
-
import AppWiki from "./icons/react/AppWiki";
|
|
20
|
-
import {copyUrlToClipboard} from "./copy-to-clipboard";
|
|
21
|
-
import {useToast} from "./toast/toast-provider";
|
|
22
9
|
import {Icon} from "./icons/Icon";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import
|
|
10
|
+
import {FileIcon} from "./file-item/file-icon";
|
|
11
|
+
import {FileMenuItems} from "./file-item/file-menu-items";
|
|
12
|
+
import {UploadFileWithContent} from "./file-item/types";
|
|
13
|
+
import {useRegisterInImageGallery} from "./file-item/use-register-in-image-gallery";
|
|
14
|
+
import {FileTitle as FileTitleInner} from "./file-item/file-title";
|
|
26
15
|
|
|
27
16
|
const fileItemStyle = css`
|
|
28
17
|
display: block;
|
|
@@ -79,32 +68,18 @@ const actionsButtonStyle = css`
|
|
|
79
68
|
opacity: 0;
|
|
80
69
|
`;
|
|
81
70
|
|
|
82
|
-
export type FileItemType = {
|
|
83
|
-
uid: string;
|
|
84
|
-
name: string;
|
|
85
|
-
url: string;
|
|
86
|
-
downloadUrl?: string | null;
|
|
87
|
-
thumbnailUrl: string | null;
|
|
88
|
-
contentType: string;
|
|
89
|
-
previewData: null | {
|
|
90
|
-
type: "image" | "video" | "iframe";
|
|
91
|
-
previewSrc: string | null;
|
|
92
|
-
originalSrc: string;
|
|
93
|
-
};
|
|
94
|
-
status?: string;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
71
|
export type FileItemProps = {
|
|
98
|
-
data:
|
|
72
|
+
data: UploadFileWithContent;
|
|
99
73
|
onDownloadClick?: () => void;
|
|
100
|
-
onRemoveClick?: (
|
|
101
|
-
onRenameClick?: (
|
|
74
|
+
onRemoveClick?: () => void;
|
|
75
|
+
onRenameClick?: (file: {id: string; name: string}) => void;
|
|
102
76
|
disabled?: boolean;
|
|
103
77
|
};
|
|
104
78
|
|
|
105
79
|
export const minFileTileWidth = 120;
|
|
106
80
|
|
|
107
81
|
export function FileItem(props: FileItemProps) {
|
|
82
|
+
const theme = useTheme();
|
|
108
83
|
const {onDownloadClick, onRemoveClick} = props;
|
|
109
84
|
const {name, thumbnailUrl, status, previewData: preview, contentType} = props.data;
|
|
110
85
|
const isPending = status === "uploading" || status === "deleting";
|
|
@@ -114,59 +89,11 @@ export function FileItem(props: FileItemProps) {
|
|
|
114
89
|
|
|
115
90
|
const showFileIcon = !isPending && !isBackgroundReady;
|
|
116
91
|
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (!preview) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
imagesRegistry.set(preview.originalSrc, {
|
|
127
|
-
type: preview.type,
|
|
128
|
-
src: preview.originalSrc,
|
|
129
|
-
label: name,
|
|
130
|
-
zoomed: false,
|
|
131
|
-
setZoomed,
|
|
132
|
-
actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
|
|
133
|
-
});
|
|
134
|
-
}, [imagesRegistry, name, preview, onDownloadClick]);
|
|
135
|
-
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
if (!preview) {
|
|
138
|
-
return undefined;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (zoomed) {
|
|
142
|
-
galleryMethods.setActivated(true);
|
|
143
|
-
}
|
|
144
|
-
const imageData = imagesRegistry.get(preview.originalSrc);
|
|
145
|
-
if (imageData) {
|
|
146
|
-
imageData.zoomed = zoomed;
|
|
147
|
-
} else {
|
|
148
|
-
imagesRegistry.set(preview.originalSrc, {
|
|
149
|
-
type: preview.type,
|
|
150
|
-
src: preview.originalSrc,
|
|
151
|
-
label: name,
|
|
152
|
-
zoomed,
|
|
153
|
-
setZoomed,
|
|
154
|
-
actions: <FilePreviewActions url={preview.originalSrc} name={name} onDownloadClick={onDownloadClick} />,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return () => {
|
|
159
|
-
imagesRegistry.delete(preview.originalSrc);
|
|
160
|
-
};
|
|
161
|
-
}, [galleryMethods, zoomed, preview, imagesRegistry, name, onDownloadClick]);
|
|
162
|
-
|
|
163
|
-
const onContainerClick = useCallback(() => {
|
|
164
|
-
if (preview) {
|
|
165
|
-
setZoomed(true);
|
|
166
|
-
} else {
|
|
167
|
-
onDownloadClick?.();
|
|
168
|
-
}
|
|
169
|
-
}, [preview, onDownloadClick]);
|
|
92
|
+
const {openGallery} = useRegisterInImageGallery({
|
|
93
|
+
preview,
|
|
94
|
+
name,
|
|
95
|
+
onDownloadClick,
|
|
96
|
+
});
|
|
170
97
|
|
|
171
98
|
return (
|
|
172
99
|
<>
|
|
@@ -219,7 +146,7 @@ export function FileItem(props: FileItemProps) {
|
|
|
219
146
|
>
|
|
220
147
|
<div
|
|
221
148
|
style={isBackgroundReady ? {backgroundImage: `url(${thumbnailUrl})`} : {}}
|
|
222
|
-
onClick={
|
|
149
|
+
onClick={openGallery}
|
|
223
150
|
className={cx(
|
|
224
151
|
css`
|
|
225
152
|
flex-shrink: 0;
|
|
@@ -321,7 +248,7 @@ export function FileItem(props: FileItemProps) {
|
|
|
321
248
|
data={props.data}
|
|
322
249
|
disabled={props.disabled}
|
|
323
250
|
actionsButtonStyle={
|
|
324
|
-
isBackgroundReady ? makeButtonColors(
|
|
251
|
+
isBackgroundReady ? makeButtonColors(themeVars.inversedTextColor, "ghost", theme) : undefined
|
|
325
252
|
}
|
|
326
253
|
onDownloadClick={onDownloadClick}
|
|
327
254
|
onRemoveClick={props.onRemoveClick}
|
|
@@ -366,16 +293,14 @@ function FileActionsMenu({
|
|
|
366
293
|
onRenameClick,
|
|
367
294
|
actionsButtonStyle,
|
|
368
295
|
}: {
|
|
369
|
-
data:
|
|
296
|
+
data: UploadFileWithContent;
|
|
370
297
|
onDownloadClick?: () => void;
|
|
371
|
-
onRemoveClick?: (
|
|
298
|
+
onRemoveClick?: () => void;
|
|
372
299
|
onRenameClick?: (data: {id: string; name: string}) => void;
|
|
373
300
|
disabled?: boolean;
|
|
374
301
|
setIsActionsOpened: (val: boolean) => void;
|
|
375
302
|
actionsButtonStyle?: CSSProperties;
|
|
376
303
|
}) {
|
|
377
|
-
const toast = useToast();
|
|
378
|
-
|
|
379
304
|
return (
|
|
380
305
|
<ActionsMenu
|
|
381
306
|
onOpenChange={setIsActionsOpened}
|
|
@@ -388,51 +313,20 @@ function FileActionsMenu({
|
|
|
388
313
|
/>
|
|
389
314
|
}
|
|
390
315
|
>
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
</ActionsMenuItem>
|
|
401
|
-
<a href={data.url} target="_blank" rel="noopener noreferrer">
|
|
402
|
-
<ActionsMenuItem Icon={RicheditorOpenLink}>
|
|
403
|
-
{isPhoneApp() ? "Open in browser" : "Open in new tab"}
|
|
404
|
-
</ActionsMenuItem>
|
|
405
|
-
</a>
|
|
406
|
-
{isPhoneApp() ? (
|
|
407
|
-
<ActionsMenuItem Icon={FileDownload} onSelect={onDownloadClick}>
|
|
408
|
-
Download
|
|
409
|
-
</ActionsMenuItem>
|
|
410
|
-
) : (
|
|
411
|
-
<a download={data.name} href={`${data.url}?attachment`}>
|
|
412
|
-
<ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
|
|
413
|
-
</a>
|
|
414
|
-
)}
|
|
415
|
-
{onRenameClick && data.status === "done" ? (
|
|
416
|
-
<>
|
|
417
|
-
<ActionsMenuSeparator />
|
|
418
|
-
<ActionsMenuItem Icon={Pencil} onSelect={() => onRenameClick?.({id: data.uid, name: data.name})}>
|
|
419
|
-
Rename
|
|
420
|
-
</ActionsMenuItem>
|
|
421
|
-
</>
|
|
422
|
-
) : null}
|
|
423
|
-
<ActionsMenuSeparator />
|
|
424
|
-
<ActionsMenuItem Icon={Delete} onSelect={() => onRemoveClick?.(data)} dangerous disabled={disabled}>
|
|
425
|
-
Delete
|
|
426
|
-
</ActionsMenuItem>
|
|
316
|
+
{
|
|
317
|
+
<FileMenuItems
|
|
318
|
+
file={data}
|
|
319
|
+
disabled={disabled}
|
|
320
|
+
onDownloadClick={onDownloadClick}
|
|
321
|
+
onRemoveClick={onRemoveClick}
|
|
322
|
+
onRenameClick={onRenameClick}
|
|
323
|
+
/>
|
|
324
|
+
}
|
|
427
325
|
</ActionsMenu>
|
|
428
326
|
);
|
|
429
327
|
}
|
|
430
328
|
|
|
431
329
|
function FileTitle({title, className}: {title: string; className?: string}) {
|
|
432
|
-
const parts = title.split(".");
|
|
433
|
-
const ext = parts.length > 1 ? "." + parts[parts.length - 1] : "";
|
|
434
|
-
const name = title.substring(0, title.length - ext.length);
|
|
435
|
-
|
|
436
330
|
return (
|
|
437
331
|
<div
|
|
438
332
|
className={cx(
|
|
@@ -458,216 +352,12 @@ function FileTitle({title, className}: {title: string; className?: string}) {
|
|
|
458
352
|
className
|
|
459
353
|
)}
|
|
460
354
|
>
|
|
461
|
-
<
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
min-width: 0;
|
|
465
|
-
align-items: center;
|
|
355
|
+
<FileTitleInner
|
|
356
|
+
title={title}
|
|
357
|
+
containerCss={css`
|
|
466
358
|
max-width: 180px;
|
|
467
359
|
`}
|
|
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>
|
|
360
|
+
/>
|
|
488
361
|
</div>
|
|
489
362
|
);
|
|
490
363
|
}
|
|
491
|
-
|
|
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
|
-
|
|
506
|
-
return (
|
|
507
|
-
<>
|
|
508
|
-
<a href={url} target="_blank" rel="noopener noreferrer">
|
|
509
|
-
<ActionsMenuItem Icon={RicheditorOpenLink}>Open in new tab</ActionsMenuItem>
|
|
510
|
-
</a>
|
|
511
|
-
<a download={name} href={`${url}?attachment`}>
|
|
512
|
-
<ActionsMenuItem Icon={FileDownload}>Download</ActionsMenuItem>
|
|
513
|
-
</a>
|
|
514
|
-
</>
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
function FileIcon({contentType}: {contentType?: string}) {
|
|
519
|
-
if (!contentType) {
|
|
520
|
-
return <AppWiki />;
|
|
521
|
-
}
|
|
522
|
-
if (contentType.startsWith("image/")) {
|
|
523
|
-
return <FileImage />;
|
|
524
|
-
}
|
|
525
|
-
if (contentType.startsWith("video/")) {
|
|
526
|
-
return <FileVideo />;
|
|
527
|
-
}
|
|
528
|
-
if (SheetsContentTypes.includes(contentType)) {
|
|
529
|
-
return <FileTable />;
|
|
530
|
-
}
|
|
531
|
-
if (ArchiveContentTypes.includes(contentType)) {
|
|
532
|
-
return <FileArchive />;
|
|
533
|
-
}
|
|
534
|
-
if (PresentationContentTypes.includes(contentType)) {
|
|
535
|
-
return <FilePresentation />;
|
|
536
|
-
}
|
|
537
|
-
if (DocumentContentTypes.includes(contentType) || contentType.startsWith("text/")) {
|
|
538
|
-
return <FileDocument />;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
return <AppWiki />;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const ArchiveContentTypes = [
|
|
545
|
-
"application/zip",
|
|
546
|
-
"application/zip-compressed",
|
|
547
|
-
"application/x-zip",
|
|
548
|
-
"application/x-zip-compressed",
|
|
549
|
-
"multipart/x-zip",
|
|
550
|
-
|
|
551
|
-
"application/x-rar-compressed",
|
|
552
|
-
"application/vnd.rar",
|
|
553
|
-
|
|
554
|
-
"application/x-7z-compressed",
|
|
555
|
-
|
|
556
|
-
"application/gzip",
|
|
557
|
-
"application/x-gzip",
|
|
558
|
-
|
|
559
|
-
"application/x-tar",
|
|
560
|
-
|
|
561
|
-
"application/x-bzip",
|
|
562
|
-
"application/x-bzip2",
|
|
563
|
-
"application/x-bzip3",
|
|
564
|
-
"application/x-bzip4",
|
|
565
|
-
|
|
566
|
-
"application/x-xz",
|
|
567
|
-
|
|
568
|
-
"application/zstd",
|
|
569
|
-
"application/x-zstd",
|
|
570
|
-
|
|
571
|
-
"application/x-lzma",
|
|
572
|
-
"application/x-lzip",
|
|
573
|
-
|
|
574
|
-
"application/x-lzh",
|
|
575
|
-
"application/x-lha",
|
|
576
|
-
|
|
577
|
-
"application/x-iso9660-image",
|
|
578
|
-
"application/x-cd-image",
|
|
579
|
-
|
|
580
|
-
"application/x-apple-diskimage",
|
|
581
|
-
|
|
582
|
-
"application/x-arj",
|
|
583
|
-
|
|
584
|
-
"application/x-cpio",
|
|
585
|
-
|
|
586
|
-
"application/x-rpm",
|
|
587
|
-
|
|
588
|
-
"application/x-deb",
|
|
589
|
-
"application/vnd.debian.binary-package",
|
|
590
|
-
|
|
591
|
-
"application/x-compress",
|
|
592
|
-
"application/x-archive",
|
|
593
|
-
"application/vnd.android.package-archive",
|
|
594
|
-
];
|
|
595
|
-
|
|
596
|
-
const PresentationContentTypes = [
|
|
597
|
-
"application/x-iwork-keynote-sffkey",
|
|
598
|
-
"application/vnd.ms-powerpoint",
|
|
599
|
-
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
600
|
-
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
|
601
|
-
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
602
|
-
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
|
603
|
-
"application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
|
|
604
|
-
"application/vnd.ms-powerpoint.template.macroEnabled.12",
|
|
605
|
-
"application/vnd.oasis.opendocument.presentation",
|
|
606
|
-
"application/vnd.oasis.opendocument.presentation-template",
|
|
607
|
-
"application/vnd.apple.keynote",
|
|
608
|
-
"application/vnd.google-apps.presentation",
|
|
609
|
-
"application/pdf",
|
|
610
|
-
"application/vnd.sun.xml.impress",
|
|
611
|
-
"application/vnd.stardivision.impress",
|
|
612
|
-
];
|
|
613
|
-
|
|
614
|
-
const SheetsContentTypes = [
|
|
615
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
616
|
-
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
617
|
-
"application/vnd.ms-excel",
|
|
618
|
-
"application/vnd.ms-excel.sheet.macroEnabled.12",
|
|
619
|
-
"application/vnd.ms-excel.template.macroEnabled.12",
|
|
620
|
-
"application/vnd.ms-excel.addin.macroEnabled.12",
|
|
621
|
-
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
|
622
|
-
"application/vnd.oasis.opendocument.spreadsheet",
|
|
623
|
-
"application/vnd.oasis.opendocument.spreadsheet-template",
|
|
624
|
-
"application/vnd.apple.numbers",
|
|
625
|
-
"application/vnd.google-apps.spreadsheet",
|
|
626
|
-
"text/csv",
|
|
627
|
-
"text/x-comma-separated-values",
|
|
628
|
-
"application/csv",
|
|
629
|
-
"text/tab-separated-values",
|
|
630
|
-
"application/vnd.lotus-1-2-3",
|
|
631
|
-
"application/x-123",
|
|
632
|
-
"application/vnd.stardivision.calc",
|
|
633
|
-
"application/vnd.sun.xml.calc",
|
|
634
|
-
"application/x-dbase",
|
|
635
|
-
"application/x-iwork-numbers-sffnumbers",
|
|
636
|
-
];
|
|
637
|
-
|
|
638
|
-
const DocumentContentTypes = [
|
|
639
|
-
"application/msword",
|
|
640
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
641
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
642
|
-
"application/vnd.ms-word.document.macroEnabled.12",
|
|
643
|
-
"application/vnd.ms-word.template.macroEnabled.12",
|
|
644
|
-
|
|
645
|
-
"application/vnd.oasis.opendocument.text",
|
|
646
|
-
"application/vnd.oasis.opendocument.text-template",
|
|
647
|
-
"application/vnd.oasis.opendocument.text-master",
|
|
648
|
-
"application/vnd.oasis.opendocument.text-web",
|
|
649
|
-
|
|
650
|
-
"application/vnd.apple.pages",
|
|
651
|
-
"application/x-iwork-pages-sffpages",
|
|
652
|
-
|
|
653
|
-
"application/rtf",
|
|
654
|
-
"text/rtf",
|
|
655
|
-
|
|
656
|
-
"text/plain",
|
|
657
|
-
"text/markdown",
|
|
658
|
-
"text/html",
|
|
659
|
-
|
|
660
|
-
"application/vnd.google-apps.document",
|
|
661
|
-
|
|
662
|
-
"application/vnd.sun.xml.writer",
|
|
663
|
-
"application/vnd.sun.xml.writer.template",
|
|
664
|
-
"application/vnd.sun.xml.writer.global",
|
|
665
|
-
|
|
666
|
-
"application/vnd.stardivision.writer",
|
|
667
|
-
"application/vnd.stardivision.writer-global",
|
|
668
|
-
|
|
669
|
-
"application/x-mswrite",
|
|
670
|
-
"application/x-abiword",
|
|
671
|
-
|
|
672
|
-
"application/pdf",
|
|
673
|
-
];
|
package/src/file-item.tsx
CHANGED
|
@@ -3,8 +3,9 @@ import {useCallback, useEffect, useState} from "react";
|
|
|
3
3
|
import {ActionsMenu, ActionsMenuItem} from "./actions-menu";
|
|
4
4
|
import {ActionsButtonCompact} from "./button/actions-button-compact";
|
|
5
5
|
import {Item} from "./item";
|
|
6
|
-
import {border,
|
|
6
|
+
import {border, fontWeight, space, textStyles, themeVars} from "./design-system";
|
|
7
7
|
import {makeButtonColors} from "./button/make-button-colors";
|
|
8
|
+
import {useTheme} from "./theme-provider";
|
|
8
9
|
import {useImagesGalleryMethods, useImagesGalleryRegistry} from "./images-gallery/images-gallery";
|
|
9
10
|
import FileDownload from "./icons/react/FileDownload";
|
|
10
11
|
import RicheditorOpenLink from "./icons/react/RicheditorOpenLink";
|
|
@@ -94,6 +95,7 @@ export type FileItemProps = {
|
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
export function FileItem(props: FileItemProps) {
|
|
98
|
+
const theme = useTheme();
|
|
97
99
|
const {onDownloadClick, onRemoveClick} = props;
|
|
98
100
|
const {name, url, thumbnailUrl, status, previewData: preview} = props.data;
|
|
99
101
|
const isActive = status === "uploading" || status === "deleting";
|
|
@@ -201,7 +203,9 @@ export function FileItem(props: FileItemProps) {
|
|
|
201
203
|
className={css`
|
|
202
204
|
z-index: 1;
|
|
203
205
|
`}
|
|
204
|
-
style={
|
|
206
|
+
style={
|
|
207
|
+
isBackgroundReady ? makeButtonColors(themeVars.inversedTextColor, "ghost", theme) : undefined
|
|
208
|
+
}
|
|
205
209
|
/>
|
|
206
210
|
}
|
|
207
211
|
>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {makeThematicPalette, SCALE_PRESETS} from "./palette-generator";
|
|
2
|
+
import {OKLCH, parse, to} from "./color-utils";
|
|
3
|
+
|
|
4
|
+
function getHue(color: string): number {
|
|
5
|
+
const oklch = to(parse(color), OKLCH);
|
|
6
|
+
return oklch.coords[2] ?? 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
describe("shiftHueTowards", () => {
|
|
10
|
+
it("no shift when baseChroma is 0", () => {
|
|
11
|
+
const palette = makeThematicPalette({
|
|
12
|
+
baseHue: 200,
|
|
13
|
+
baseChroma: 0,
|
|
14
|
+
accentHue: 264,
|
|
15
|
+
accentChroma: 0.16,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Semantic colors should keep original hues (within 1° tolerance)
|
|
19
|
+
expect(Math.abs(getHue(palette.red[9]) - SCALE_PRESETS.red.hue)).toBeLessThan(1);
|
|
20
|
+
expect(Math.abs(getHue(palette.teal[9]) - SCALE_PRESETS.teal.hue)).toBeLessThan(1);
|
|
21
|
+
expect(Math.abs(getHue(palette.yellow[9]) - SCALE_PRESETS.yellow.hue)).toBeLessThan(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("shifts hue towards baseHue when baseChroma is high", () => {
|
|
25
|
+
const palette = makeThematicPalette({
|
|
26
|
+
baseHue: 200, // blue-ish
|
|
27
|
+
baseChroma: 0.15, // high chroma → 30% shift
|
|
28
|
+
accentHue: 264,
|
|
29
|
+
accentChroma: 0.16,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const redHue = getHue(palette.red[9]);
|
|
33
|
+
const tealHue = getHue(palette.teal[9]);
|
|
34
|
+
const yellowHue = getHue(palette.yellow[9]);
|
|
35
|
+
|
|
36
|
+
// Hues should differ from original presets
|
|
37
|
+
expect(redHue).not.toBeCloseTo(SCALE_PRESETS.red.hue, 0);
|
|
38
|
+
expect(tealHue).not.toBeCloseTo(SCALE_PRESETS.teal.hue, 0);
|
|
39
|
+
expect(yellowHue).not.toBeCloseTo(SCALE_PRESETS.yellow.hue, 0);
|
|
40
|
+
|
|
41
|
+
// Teal (183) should shift towards 200 → increases
|
|
42
|
+
expect(tealHue).toBeGreaterThan(SCALE_PRESETS.teal.hue);
|
|
43
|
+
expect(tealHue).toBeLessThan(200);
|
|
44
|
+
|
|
45
|
+
// Yellow (100) should shift towards 200 → increases
|
|
46
|
+
expect(yellowHue).toBeGreaterThan(SCALE_PRESETS.yellow.hue);
|
|
47
|
+
expect(yellowHue).toBeLessThan(200);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("handles hue wrap-around correctly", () => {
|
|
51
|
+
// Base hue near 0, target hue near 360
|
|
52
|
+
const palette = makeThematicPalette({
|
|
53
|
+
baseHue: 350, // near red
|
|
54
|
+
baseChroma: 0.15,
|
|
55
|
+
accentHue: 264,
|
|
56
|
+
accentChroma: 0.16,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Red (19) is close to 350 via wrap-around (350 → 360 → 19 = 29° distance)
|
|
60
|
+
// Should shift towards 350, so should decrease or wrap
|
|
61
|
+
const redHue = getHue(palette.red[9]);
|
|
62
|
+
// The shift should take the shortest path
|
|
63
|
+
expect(Math.abs(redHue - 350) < 30 || Math.abs(redHue - 350 + 360) < 30).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("caps shift at 30%", () => {
|
|
67
|
+
const lowChroma = makeThematicPalette({
|
|
68
|
+
baseHue: 150, // green
|
|
69
|
+
baseChroma: 0.05, // 10% shift
|
|
70
|
+
accentHue: 264,
|
|
71
|
+
accentChroma: 0.16,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const highChroma = makeThematicPalette({
|
|
75
|
+
baseHue: 150,
|
|
76
|
+
baseChroma: 0.25, // would be 50% but capped at 30%
|
|
77
|
+
accentHue: 264,
|
|
78
|
+
accentChroma: 0.16,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const lowShiftYellow = getHue(lowChroma.yellow[9]);
|
|
82
|
+
const highShiftYellow = getHue(highChroma.yellow[9]);
|
|
83
|
+
|
|
84
|
+
// Yellow (100) should shift towards 150 → increases
|
|
85
|
+
// Higher chroma = more shift (up to 30% cap)
|
|
86
|
+
expect(lowShiftYellow).toBeGreaterThan(SCALE_PRESETS.yellow.hue);
|
|
87
|
+
expect(highShiftYellow).toBeGreaterThan(lowShiftYellow);
|
|
88
|
+
// But capped - 30% of 50° = 15° max additional shift
|
|
89
|
+
expect(highShiftYellow).toBeLessThan(150);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
// This icon file is generated automatically.
|
|
3
|
+
|
|
4
|
+
import { IconDefinition } from '../types';
|
|
5
|
+
|
|
6
|
+
const FileCounter: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"d":"M11.742 1.5a.75.75 0 0 1 .53.219l4.504 4.497a.752.752 0 0 1-.529 1.281h-3.672a1.583 1.583 0 0 1-1.582-1.584V3H5.745c-.69 0-1.249.56-1.249 1.25v11.5c0 .69.56 1.25 1.25 1.25h3.501a.75.75 0 0 1 0 1.5H5.745a2.749 2.749 0 0 1-2.748-2.75V4.25c0-1.519 1.23-2.75 2.748-2.75h5.997Zm2.173 8c1.668 0 2.795.902 2.795 2.281 0 1.093-.717 1.81-1.647 2.019v.036c1.176.12 1.937.872 1.937 2.06 0 1.565-1.242 2.604-3.074 2.604-1.504 0-2.428-.71-2.8-1.559a1.393 1.393 0 0 1-.126-.567c0-.466.274-.759.727-.759.329 0 .537.144.7.472.28.603.706.962 1.526.962.81 0 1.368-.514 1.368-1.23.006-.837-.558-1.302-1.515-1.302h-.345c-.399 0-.629-.257-.629-.645 0-.376.23-.64.629-.64h.323c.826 0 1.361-.49 1.361-1.194 0-.693-.426-1.152-1.224-1.152-.667 0-1.072.304-1.33.913-.18.406-.371.556-.743.556-.46 0-.695-.293-.695-.729 0-.203.038-.376.12-.58.35-.841 1.247-1.546 2.642-1.546Zm-1.423-3.587a.084.084 0 0 0 .083.084h1.86l-1.943-1.94v1.856Z"},"children":[]}],"metadata":""}]},"name":"file-counter"};
|
|
7
|
+
|
|
8
|
+
export default FileCounter;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
// This icon file is generated automatically.
|
|
3
|
+
|
|
4
|
+
import { IconDefinition } from '../types';
|
|
5
|
+
|
|
6
|
+
const FileMultiple: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"path","properties":{"d":"M12.742 1a.75.75 0 0 1 .53.219l4.504 4.497c.141.14.22.332.22.531v6.003A2.75 2.75 0 0 1 15.249 15h-.473a2.748 2.748 0 0 1-2.233 2.265l-6.405 1.129a2.749 2.749 0 0 1-3.183-2.23L1.477 7.791a2.75 2.75 0 0 1 2.23-3.186l2.29-.404V3.75A2.75 2.75 0 0 1 8.745 1h3.997ZM3.967 6.084a1.25 1.25 0 0 0-1.013 1.447l1.475 8.371a1.25 1.25 0 0 0 1.448 1.015l6.404-1.13c.45-.08.798-.39.95-.787H8.744a2.75 2.75 0 0 1-2.748-2.75V5.726l-2.03.358ZM8.745 2.5c-.69 0-1.25.56-1.25 1.25v8.5c0 .69.56 1.25 1.25 1.25h6.503c.69 0 1.249-.56 1.249-1.25V6.997h-2.922a1.584 1.584 0 0 1-1.582-1.584V2.5H8.745Zm4.747 2.913c0 .022.009.044.024.06a.085.085 0 0 0 .059.024h1.86l-1.943-1.94v1.856Z"},"children":[]}],"metadata":""}]},"name":"file-multiple"};
|
|
7
|
+
|
|
8
|
+
export default FileMultiple;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
// This icon file is generated automatically.
|
|
3
|
+
|
|
4
|
+
import { IconDefinition } from '../types';
|
|
5
|
+
|
|
6
|
+
const ValueEdit: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"width":20,"height":20},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","clipRule":"evenodd","d":"M3.5 6.25a.75.75 0 0 1 .75-.75h11.5a.75.75 0 0 1 .75.75v2a.75.75 0 0 0 1.5 0v-2A2.25 2.25 0 0 0 15.75 4H4.25A2.25 2.25 0 0 0 2 6.25v5.5A2.25 2.25 0 0 0 4.25 14H12a.75.75 0 0 0 0-1.5H4.25a.75.75 0 0 1-.75-.75v-5.5Zm2.25 2a.75.75 0 0 0 0 1.5h2.5a.75.75 0 0 0 0-1.5h-2.5Zm9 2a.75.75 0 0 0 0 1.5h1v4.5h-1a.75.75 0 0 0 0 1.5h3.5a.75.75 0 0 0 0-1.5h-1v-4.5h1a.75.75 0 0 0 0-1.5h-3.5Z"},"children":[]}],"metadata":""}]},"name":"value-edit"};
|
|
7
|
+
|
|
8
|
+
export default ValueEdit;
|
package/src/icons/ast/index.tsx
CHANGED
|
@@ -133,9 +133,11 @@ export { default as Fields } from './Fields';
|
|
|
133
133
|
export { default as Figma } from './Figma';
|
|
134
134
|
export { default as FileArchive } from './FileArchive';
|
|
135
135
|
export { default as FileBroken } from './FileBroken';
|
|
136
|
+
export { default as FileCounter } from './FileCounter';
|
|
136
137
|
export { default as FileDocument } from './FileDocument';
|
|
137
138
|
export { default as FileDownload } from './FileDownload';
|
|
138
139
|
export { default as FileImage } from './FileImage';
|
|
140
|
+
export { default as FileMultiple } from './FileMultiple';
|
|
139
141
|
export { default as FilePresentation } from './FilePresentation';
|
|
140
142
|
export { default as FileTable } from './FileTable';
|
|
141
143
|
export { default as FileUpload } from './FileUpload';
|
|
@@ -404,6 +406,7 @@ export { default as UserGroupRemove } from './UserGroupRemove';
|
|
|
404
406
|
export { default as UserGroup } from './UserGroup';
|
|
405
407
|
export { default as UserRole } from './UserRole';
|
|
406
408
|
export { default as UserX } from './UserX';
|
|
409
|
+
export { default as ValueEdit } from './ValueEdit';
|
|
407
410
|
export { default as ViewAi } from './ViewAi';
|
|
408
411
|
export { default as ViewBoard } from './ViewBoard';
|
|
409
412
|
export { default as ViewCalendar } from './ViewCalendar';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This icon file is generated automatically.
|
|
2
|
+
|
|
3
|
+
import {forwardRef} from 'react';
|
|
4
|
+
import FileCounterSvg from '../ast/FileCounter';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { IconBaseProps } from '../types';
|
|
7
|
+
|
|
8
|
+
const FileCounter = forwardRef<SVGSVGElement, IconBaseProps>(function FileCounter(
|
|
9
|
+
props: IconBaseProps,
|
|
10
|
+
ref: React.Ref<SVGSVGElement>
|
|
11
|
+
) {return <Icon {...props} className={props.className} ref={ref} icon={FileCounterSvg} />});
|
|
12
|
+
|
|
13
|
+
export default FileCounter;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This icon file is generated automatically.
|
|
2
|
+
|
|
3
|
+
import {forwardRef} from 'react';
|
|
4
|
+
import FileMultipleSvg from '../ast/FileMultiple';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { IconBaseProps } from '../types';
|
|
7
|
+
|
|
8
|
+
const FileMultiple = forwardRef<SVGSVGElement, IconBaseProps>(function FileMultiple(
|
|
9
|
+
props: IconBaseProps,
|
|
10
|
+
ref: React.Ref<SVGSVGElement>
|
|
11
|
+
) {return <Icon {...props} className={props.className} ref={ref} icon={FileMultipleSvg} />});
|
|
12
|
+
|
|
13
|
+
export default FileMultiple;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This icon file is generated automatically.
|
|
2
|
+
|
|
3
|
+
import {forwardRef} from 'react';
|
|
4
|
+
import ValueEditSvg from '../ast/ValueEdit';
|
|
5
|
+
import { Icon } from '../Icon';
|
|
6
|
+
import { IconBaseProps } from '../types';
|
|
7
|
+
|
|
8
|
+
const ValueEdit = forwardRef<SVGSVGElement, IconBaseProps>(function ValueEdit(
|
|
9
|
+
props: IconBaseProps,
|
|
10
|
+
ref: React.Ref<SVGSVGElement>
|
|
11
|
+
) {return <Icon {...props} className={props.className} ref={ref} icon={ValueEditSvg} />});
|
|
12
|
+
|
|
13
|
+
export default ValueEdit;
|