@beydesign/storybook 0.2.29 → 0.2.30
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/dist/stories/Form/Dropdown.js +38 -31
- package/dist/stories/Form/FileUpload/FileUpload.js +26 -16
- package/dist/stories/Form/FileUpload/FileUploading.js +35 -25
- package/dist/stories/Form/FileUpload/UploadedFile.js +15 -4
- package/dist/stories/Form/FileUpload/UploadedFile.stories.js +21 -26
- package/dist/stories/Form/types.d.ts +5 -9
- package/dist/stories/UI/Menu.js +3 -1
- package/dist/stories/UI/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { DropdownType } from './types';
|
|
4
|
-
import { Box, CircularProgress, ClickAwayListener, Popper, } from '@mui/material';
|
|
4
|
+
import { Box, CircularProgress, ClickAwayListener, Grow, Popper, } from '@mui/material';
|
|
5
5
|
import { Typography, TypographySize, TypographyWeight } from '../Typography';
|
|
6
6
|
import { getIconComponent } from '../../utils';
|
|
7
7
|
import { Checkbox } from './Checkbox';
|
|
@@ -152,7 +152,10 @@ export const Dropdown = ({ disabled = false, placeholder = 'Select an option', l
|
|
|
152
152
|
? 'var(--color-border-border-brand)'
|
|
153
153
|
: 'var(--color-border-border-component)'}`, borderRadius: '4px', bgcolor: disabled
|
|
154
154
|
? 'var(--color-background-bg-component-disabled)'
|
|
155
|
-
: 'var(--color-background-bg-component)', position: 'relative', onClick: () => !disabled && setOpen((prev) => !prev), onKeyDown: handleKeyDown, tabIndex: disabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": open, "aria-disabled": disabled, role: "combobox", sx: {
|
|
155
|
+
: 'var(--color-background-bg-component)', position: 'relative', onClick: () => !disabled && setOpen((prev) => !prev), onKeyDown: handleKeyDown, tabIndex: disabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": open, "aria-disabled": disabled, role: "combobox", sx: {
|
|
156
|
+
boxSizing: 'border-box',
|
|
157
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
158
|
+
}, children: [_jsx(Box, { display: "flex", flexDirection: "row", alignItems: "center", gap: "var(--spacing-tokens-size-in-px-spacing-spacing-sm)", flexGrow: 1, minWidth: 0, overflow: "hidden", children: hasSelection && (hasRichSelection || hasAvatarOption) ? (_jsxs(_Fragment, { children: [hasAvatarOption && (_jsx(Box, { flexShrink: 0, display: "flex", children: _jsx(Avatar, { image: selectedOptions[0].avatar, text: selectedOptions[0].label, size: AvatarSize.xs, border: true }) })), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: "var(--color-text-text-title)", textStyle: {
|
|
156
159
|
minWidth: 0,
|
|
157
160
|
textAlign: 'left',
|
|
158
161
|
overflow: 'hidden',
|
|
@@ -177,8 +180,8 @@ export const Dropdown = ({ disabled = false, placeholder = 'Select an option', l
|
|
|
177
180
|
showClear &&
|
|
178
181
|
hasSelection &&
|
|
179
182
|
getIconComponent('X', {
|
|
180
|
-
width: '
|
|
181
|
-
height: '
|
|
183
|
+
width: '20px',
|
|
184
|
+
height: '20px',
|
|
182
185
|
color: 'var(--color-foreground-fg-secondary)',
|
|
183
186
|
onClick: handleClear,
|
|
184
187
|
'aria-label': 'Clear selection',
|
|
@@ -191,33 +194,37 @@ export const Dropdown = ({ disabled = false, placeholder = 'Select an option', l
|
|
|
191
194
|
}
|
|
192
195
|
},
|
|
193
196
|
}), !disabled &&
|
|
194
|
-
getIconComponent(
|
|
195
|
-
width: '
|
|
196
|
-
height: '
|
|
197
|
+
getIconComponent('CaretDown', {
|
|
198
|
+
width: '20px',
|
|
199
|
+
height: '20px',
|
|
197
200
|
color: 'var(--color-foreground-fg-secondary)',
|
|
198
201
|
'aria-hidden': 'true',
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
backgroundColor:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
202
|
+
style: {
|
|
203
|
+
transition: 'transform 200ms ease',
|
|
204
|
+
transform: open ? 'rotate(180deg)' : 'rotate(0deg)',
|
|
205
|
+
},
|
|
206
|
+
})] })] }), _jsx(Popper, { open: open, anchorEl: anchorRef.current, placement: "bottom-start", transition: true, style: { width: anchorRef.current?.offsetWidth, zIndex: 1300 }, children: ({ TransitionProps }) => (_jsx(Grow, { ...TransitionProps, timeout: 200, style: { transformOrigin: 'top' }, children: _jsxs(Box, { ref: optionsContainerRef, onScroll: handleOptionsScroll, bgcolor: 'var(--color-background-bg-component)', borderRadius: '4px', width: '100%', maxHeight: '200px', overflow: 'auto', boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)', mt: '4px', role: "listbox", sx: {
|
|
207
|
+
border: '1px solid var(--color-border-border-component)',
|
|
208
|
+
}, children: [normalizedOptions.length === 0 && !isLoadingMore ? (_jsx(Box, { display: 'flex', flexDirection: 'row', paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', paddingY: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, children: "No options found" }) })) : (normalizedOptions.map((option, index) => (_jsxs(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', height: '36px', padding: '0 var(--spacing-tokens-size-in-px-spacing-spacing-md)', onClick: () => handleOptionSelect(option.value), onMouseEnter: () => setHighlightedIndex(index), sx: {
|
|
209
|
+
cursor: 'pointer',
|
|
210
|
+
backgroundColor: highlightedIndex === index
|
|
211
|
+
? 'var(--color-background-bg-secondary-action-hover)'
|
|
212
|
+
: 'transparent',
|
|
213
|
+
'&:hover': {
|
|
214
|
+
backgroundColor: 'var(--color-background-bg-secondary-action-hover)',
|
|
215
|
+
},
|
|
216
|
+
width: '100%',
|
|
217
|
+
boxSizing: 'border-box',
|
|
218
|
+
}, role: "option", "aria-selected": isOptionSelected(option.value), children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', flexGrow: 1, minWidth: 0, overflow: "hidden", children: [showCheckboxes && (_jsx(Box, { flexShrink: 0, children: _jsx(Checkbox, { checked: isOptionSelected(option.value), onChange: () => handleOptionSelect(option.value), style: { margin: 0, padding: 0 } }) })), hasAvatarOption && (_jsx(Box, { flexShrink: 0, display: "flex", children: _jsx(Avatar, { image: option.avatar, text: option.label, size: AvatarSize.xs, border: true }) })), _jsx(Box, { flexGrow: 1, minWidth: 0, overflow: "hidden", children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: "var(--color-text-text-title)", textStyle: {
|
|
219
|
+
overflow: 'hidden',
|
|
220
|
+
textOverflow: 'ellipsis',
|
|
221
|
+
whiteSpace: 'nowrap',
|
|
222
|
+
width: '100%',
|
|
223
|
+
}, children: option.label }) }), option.badge && (_jsx(Box, { flexShrink: 0, children: _jsx(Badge, { size: BadgeSize.xs, color: BadgeColor.Default, text: option.badge }) }))] }), _jsx(Box, { flexShrink: 0, display: "flex", alignItems: "center", children: showTicks &&
|
|
224
|
+
isOptionSelected(option.value) &&
|
|
225
|
+
getIconComponent('Check', {
|
|
226
|
+
width: '20px',
|
|
227
|
+
height: '20px',
|
|
228
|
+
color: 'var(--color-foreground-fg-brand-primary)',
|
|
229
|
+
}) })] }, option.value)))), isLoadingMore && (_jsx(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', height: '36px', width: '100%', role: "status", "aria-label": "Loading more options", children: _jsx(CircularProgress, { size: 20, sx: { color: 'var(--color-foreground-fg-brand-primary)' } }) }))] }) })) })] }) }));
|
|
223
230
|
};
|
|
@@ -55,14 +55,20 @@ export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,
|
|
|
55
55
|
.split(',')
|
|
56
56
|
.map((ext) => ext.trim())
|
|
57
57
|
.filter((ext) => ext.startsWith('.'));
|
|
58
|
-
//
|
|
59
|
-
|
|
58
|
+
// Collect one icon per accepted file type, de-duplicated by component
|
|
59
|
+
// identity (e.g. `.doc` and `.docx` share FileDoc) while preserving order.
|
|
60
|
+
// NB: we can't key on `IconComponent.name` — Phosphor icons are forwardRef
|
|
61
|
+
// objects with no `name`, so every entry would collapse to a single key.
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
const icons = [];
|
|
60
64
|
extensions.forEach((ext) => {
|
|
61
65
|
const IconComponent = fileIconMap[ext] || defaultIcon;
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if (!seen.has(IconComponent)) {
|
|
67
|
+
seen.add(IconComponent);
|
|
68
|
+
icons.push(IconComponent);
|
|
69
|
+
}
|
|
64
70
|
});
|
|
65
|
-
return
|
|
71
|
+
return icons;
|
|
66
72
|
};
|
|
67
73
|
const fileIcons = getFileTypeIcons();
|
|
68
74
|
const handleFileSelect = (files) => {
|
|
@@ -104,25 +110,29 @@ export const FileUpload = ({ disabled, sx, acceptedFileTypes = '.pdf,.doc,.docx,
|
|
|
104
110
|
handleFileSelect(e.target.files);
|
|
105
111
|
};
|
|
106
112
|
const iconProps = {
|
|
107
|
-
height: '
|
|
108
|
-
width: '
|
|
113
|
+
height: '24px',
|
|
114
|
+
width: '24px',
|
|
109
115
|
color: disabled
|
|
110
116
|
? 'var(--color-text-text-subtle)'
|
|
111
117
|
: 'var(--color-text-text-paragraph)',
|
|
112
118
|
};
|
|
113
|
-
return (_jsxs(Box, { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', border: `
|
|
114
|
-
? 'var(--color-
|
|
119
|
+
return (_jsxs(Box, { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', border: `1px dashed ${disabled
|
|
120
|
+
? 'var(--color-border-border-disabled)'
|
|
121
|
+
: isDragging
|
|
122
|
+
? 'var(--color-border-border-brand-hover)'
|
|
123
|
+
: 'var(--color-border-border-component)'}`, bgcolor: disabled
|
|
124
|
+
? 'var(--color-background-bg-component-disabled)'
|
|
115
125
|
: isDragging
|
|
116
126
|
? 'var(--color-background-bg-component-hover)'
|
|
117
|
-
: 'var(--color-background-bg-element)', sx: { cursor: disabled ? 'not-allowed' : 'pointer', ...sx }, onClick: handleClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [_jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, accept: acceptedFileTypes, onChange: handleInputChange, disabled: disabled }), _jsx(Box, { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', border: `
|
|
118
|
-
? 'var(--color-border-border-
|
|
119
|
-
:
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
: 'var(--color-background-bg-element)', sx: { cursor: disabled ? 'not-allowed' : 'pointer', ...sx }, onClick: handleClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [_jsx("input", { type: "file", ref: fileInputRef, style: { display: 'none' }, accept: acceptedFileTypes, onChange: handleInputChange, disabled: disabled }), _jsx(Box, { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', border: `1px solid ${disabled
|
|
128
|
+
? 'var(--color-border-border-disabled)'
|
|
129
|
+
: 'var(--color-border-border-component)'}`, borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', bgcolor: disabled
|
|
130
|
+
? 'var(--color-background-bg-button-disabled)'
|
|
131
|
+
: 'var(--color-background-bg-element)', children: _jsx(UploadSimple, { height: '20px', width: '20px', weight: "bold", color: disabled
|
|
122
132
|
? 'var(--color-foreground-fg-disabled)'
|
|
123
133
|
: 'var(--color-foreground-fg-brand-primary)' }) }), _jsxs(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', children: [_jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.SemiBold, color: disabled
|
|
134
|
+
? 'var(--color-text-text-inactive)'
|
|
135
|
+
: 'var(--color-text-text-clicable)', textStyle: { cursor: disabled ? 'not-allowed' : 'pointer' }, children: "Click to upload" }), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: disabled
|
|
124
136
|
? 'var(--color-text-text-disabled)'
|
|
125
|
-
: 'var(--color-text-text-accent)', textStyle: { cursor: disabled ? 'not-allowed' : 'pointer' }, children: "Click to upload" }), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: disabled
|
|
126
|
-
? 'var(--color-text-text-subtle)'
|
|
127
137
|
: 'var(--color-text-text-paragraph)', children: "or drag and drop" }), _jsxs(Box, { display: 'flex', flexDirection: 'row', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', children: [fileIcons.map((Icon, index) => (_jsx(Icon, { ...iconProps }, index))), fileIcons.length === 0 && _jsx(FileCode, { ...iconProps })] })] })] }));
|
|
128
138
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment } from 'react';
|
|
3
2
|
import { FileUploadingStatus, FileUploadingProgressMode, } from '../types';
|
|
4
3
|
import { Box } from '@mui/material';
|
|
5
4
|
import { Typography, TypographySize, TypographyWeight } from '../../Typography';
|
|
@@ -7,7 +6,18 @@ import { getIconComponent } from '../../../utils';
|
|
|
7
6
|
import { Player } from '@lottiefiles/react-lottie-player';
|
|
8
7
|
import loadingAnimation from '../../../assets/animations/loading-animation.json';
|
|
9
8
|
import { ProgressIndicator, ProgressIndicatorMode } from '../../UI';
|
|
10
|
-
|
|
9
|
+
// Transparent, subtly shadowed frame that wraps a trailing action icon,
|
|
10
|
+
// matching the "Button" node in the Figma design.
|
|
11
|
+
const actionButtonSx = {
|
|
12
|
+
display: 'flex',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
justifyContent: 'center',
|
|
15
|
+
padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)',
|
|
16
|
+
borderRadius: 'var(--spacing-tokens-size-in-px-radius-radius-xs)',
|
|
17
|
+
boxShadow: '0px 1px 1px rgba(25, 28, 31, 0.05)',
|
|
18
|
+
backgroundColor: 'transparent',
|
|
19
|
+
};
|
|
20
|
+
export const FileUploading = ({ uploadProgress, uploadingStatus, progressMode = FileUploadingProgressMode.Percentage, sx, onCancel, onRetry, fileName, showCancel, showRetry, }) => {
|
|
11
21
|
const isUploading = uploadingStatus === FileUploadingStatus.Uploading;
|
|
12
22
|
const isSuccess = uploadingStatus === FileUploadingStatus.Success;
|
|
13
23
|
const isError = uploadingStatus === FileUploadingStatus.Error;
|
|
@@ -23,27 +33,27 @@ export const FileUploading = ({ uploadProgress, uploadingStatus, progressMode =
|
|
|
23
33
|
return 'FileTxt';
|
|
24
34
|
return 'File';
|
|
25
35
|
};
|
|
26
|
-
return (_jsxs(Box, { display: 'flex', flexDirection: 'column',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
isUploading &&
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
return (_jsxs(Box, { display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)', paddingY: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', border: `1px solid ${isError ? 'var(--color-border-border-error)' : 'var(--color-border-border-divider)'}`, bgcolor: isError
|
|
37
|
+
? 'var(--color-background-bg-badge-accent-red)'
|
|
38
|
+
: 'var(--color-background-bg-component-contrast-subtle)', minWidth: '300px', sx: { ...sx }, children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', width: '100%', children: [getIconComponent(getFileIcon(), {
|
|
39
|
+
width: '24px',
|
|
40
|
+
height: '24px',
|
|
41
|
+
color: isError
|
|
42
|
+
? 'var(--color-text-text-error)'
|
|
43
|
+
: 'var(--color-foreground-fg-primary)',
|
|
44
|
+
}), _jsx(Box, { flex: 1, minWidth: 0, children: _jsx(Typography, { size: TypographySize.TextS, weight: isError ? TypographyWeight.SemiBold : TypographyWeight.Regular, color: isError
|
|
45
|
+
? 'var(--color-text-text-error)'
|
|
46
|
+
: 'var(--color-text-text-title)', children: fileName }) }), isUploading && showCancel && onCancel && (_jsx(Box, { onClick: onCancel, sx: { ...actionButtonSx, cursor: 'pointer' }, children: getIconComponent('X', {
|
|
47
|
+
width: '20px',
|
|
48
|
+
height: '20px',
|
|
49
|
+
color: 'var(--color-text-text-title)',
|
|
50
|
+
}) })), isSuccess && (_jsx(Box, { sx: actionButtonSx, children: getIconComponent('CheckCircle', {
|
|
51
|
+
width: '20px',
|
|
52
|
+
height: '20px',
|
|
53
|
+
weight: 'fill',
|
|
54
|
+
color: 'var(--color-foreground-fg-success)',
|
|
55
|
+
}) }))] }), _jsxs(Box, { display: 'flex', flexDirection: 'column', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', width: '100%', children: [isUploading && isAnimationProgress && (_jsx(Player, { autoplay: true, loop: true, src: loadingAnimation, style: { height: '100%', width: '100%' } })), ((isUploading && isPercentageProgress) || isSuccess) && (_jsx(ProgressIndicator, { currentValue: isSuccess ? 100 : uploadProgress || 0, maxValue: 100, mode: ProgressIndicatorMode.Percentage, fillColor: 'var(--color-foreground-fg-violet)', backgroundColor: 'var(--color-background-bg-element)', textColor: 'var(--color-text-text-paragraph)', minWidth: 0, style: {
|
|
56
|
+
width: '100%',
|
|
57
|
+
gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)',
|
|
58
|
+
} })), isError && (_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'baseline', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', width: '100%', children: [_jsx(Typography, { size: TypographySize.TextXS, weight: TypographyWeight.Regular, color: 'var(--color-text-text-error)', children: "Upload failed, please try again" }), showRetry && onRetry && (_jsx(Box, { onClick: onRetry, style: { cursor: 'pointer' }, children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-error)', children: "Try again" }) }))] }))] })] }));
|
|
49
59
|
};
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { FileType } from '../types';
|
|
3
4
|
import { Box } from '@mui/material';
|
|
4
5
|
import { File } from '@phosphor-icons/react';
|
|
5
6
|
import { Typography, TypographySize, TypographyWeight } from '../../Typography';
|
|
6
|
-
import {
|
|
7
|
-
|
|
7
|
+
import { Menu } from '../../UI';
|
|
8
|
+
import { ButtonHierarchy, ButtonSize } from '../../Buttons';
|
|
9
|
+
export const UploadedFile = ({ type = FileType.Default, showMenu = true, menuItems, fileName, sx, }) => {
|
|
8
10
|
const isSampleFile = type === FileType.Sample;
|
|
9
|
-
|
|
11
|
+
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
12
|
+
// While its overflow menu is open, the row takes on the active highlight so
|
|
13
|
+
// it stands out from the other files in the list.
|
|
14
|
+
const backgroundColor = isMenuOpen
|
|
15
|
+
? 'var(--color-background-bg-component-hover)'
|
|
16
|
+
: isSampleFile
|
|
10
17
|
? 'var(--color-background-bg-card-highlight)'
|
|
11
|
-
: 'var(--color-background-bg-
|
|
18
|
+
: 'var(--color-background-bg-element)';
|
|
19
|
+
return (_jsx(Box, { display: 'flex', flexDirection: 'column', alignItems: 'flex-start', paddingLeft: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', paddingRight: 'var(--spacing-tokens-size-in-px-spacing-spacing-sm)', paddingY: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', borderRadius: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', bgcolor: backgroundColor, minWidth: '240px', sx: { ...sx }, children: _jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', width: '100%', children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', flex: 1, minWidth: 0, children: [_jsx(File, { width: '20px', height: '20px', color: 'var(--color-foreground-fg-secondary)' }), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: 'var(--color-text-text-title)', children: fileName })] }), showMenu && (_jsx(Menu, { icon: "DotsThree", iconWeight: "bold", items: menuItems, size: ButtonSize.xs, hierarchy: ButtonHierarchy.Tertiary, onOpenChange: setIsMenuOpen, style: {
|
|
20
|
+
background: 'transparent',
|
|
21
|
+
boxShadow: '0px 1px 1px rgba(25, 28, 31, 0.05)',
|
|
22
|
+
} }))] }) }));
|
|
12
23
|
};
|
|
@@ -23,25 +23,15 @@ const meta = {
|
|
|
23
23
|
description: 'The type of the file',
|
|
24
24
|
table: { type: { summary: 'string' } },
|
|
25
25
|
},
|
|
26
|
-
|
|
26
|
+
showMenu: {
|
|
27
27
|
control: 'boolean',
|
|
28
|
-
description: 'Whether to show the
|
|
28
|
+
description: 'Whether to show the trailing overflow-menu (kebab) button',
|
|
29
29
|
table: { type: { summary: 'boolean' } },
|
|
30
30
|
},
|
|
31
|
-
|
|
32
|
-
control: '
|
|
33
|
-
description: '
|
|
34
|
-
table: { type: { summary: '
|
|
35
|
-
},
|
|
36
|
-
onDelete: {
|
|
37
|
-
action: 'onDelete',
|
|
38
|
-
description: 'Callback function when the delete button is clicked',
|
|
39
|
-
table: { type: { summary: 'function' } },
|
|
40
|
-
},
|
|
41
|
-
onDownload: {
|
|
42
|
-
action: 'onDownload',
|
|
43
|
-
description: 'Callback function when the download button is clicked',
|
|
44
|
-
table: { type: { summary: 'function' } },
|
|
31
|
+
menuItems: {
|
|
32
|
+
control: 'object',
|
|
33
|
+
description: 'Items rendered in the overflow (kebab) menu',
|
|
34
|
+
table: { type: { summary: 'MenuItemProps[]' } },
|
|
45
35
|
},
|
|
46
36
|
sx: {
|
|
47
37
|
control: 'object',
|
|
@@ -51,23 +41,28 @@ const meta = {
|
|
|
51
41
|
},
|
|
52
42
|
};
|
|
53
43
|
export default meta;
|
|
44
|
+
const sampleMenuItems = [
|
|
45
|
+
{ label: 'Download', icon: 'DownloadSimple', onClick: () => { } },
|
|
46
|
+
{
|
|
47
|
+
label: 'Delete',
|
|
48
|
+
icon: 'Trash',
|
|
49
|
+
onClick: () => { },
|
|
50
|
+
destructive: true,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
54
53
|
export const Default = {
|
|
55
54
|
args: {
|
|
56
|
-
fileName: '
|
|
55
|
+
fileName: 'File name sample.csv',
|
|
57
56
|
type: FileType.Default,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
onDelete: () => { },
|
|
61
|
-
onDownload: () => { },
|
|
57
|
+
showMenu: true,
|
|
58
|
+
menuItems: sampleMenuItems,
|
|
62
59
|
},
|
|
63
60
|
};
|
|
64
61
|
export const Sample = {
|
|
65
62
|
args: {
|
|
66
|
-
fileName: 'sample.
|
|
63
|
+
fileName: 'File name sample.csv',
|
|
67
64
|
type: FileType.Sample,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
onDelete: () => { },
|
|
71
|
-
onDownload: () => { },
|
|
65
|
+
showMenu: true,
|
|
66
|
+
menuItems: sampleMenuItems,
|
|
72
67
|
},
|
|
73
68
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SxProps, Theme } from '@mui/material';
|
|
2
|
-
import { HintBubbleProps } from '../UI';
|
|
2
|
+
import { HintBubbleProps, MenuItemProps } from '../UI';
|
|
3
3
|
import { IconName } from '../../utils';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
/**
|
|
@@ -165,14 +165,10 @@ export interface UploadedFileProps {
|
|
|
165
165
|
type?: FileType;
|
|
166
166
|
/** File name */
|
|
167
167
|
fileName: string;
|
|
168
|
-
/** Whether to show the
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
|
|
172
|
-
/** Whether to show the download button */
|
|
173
|
-
showDownload?: boolean;
|
|
174
|
-
/** Callback function when the download button is clicked */
|
|
175
|
-
onDownload?: () => void;
|
|
168
|
+
/** Whether to show the trailing overflow-menu (kebab) button */
|
|
169
|
+
showMenu?: boolean;
|
|
170
|
+
/** Items rendered in the overflow (kebab) menu, e.g. Download / Delete */
|
|
171
|
+
menuItems?: MenuItemProps[];
|
|
176
172
|
/** Style of the uploaded file */
|
|
177
173
|
sx?: SxProps<Theme>;
|
|
178
174
|
}
|
package/dist/stories/UI/Menu.js
CHANGED
|
@@ -4,14 +4,16 @@ import { Fragment, useState } from 'react';
|
|
|
4
4
|
import { MainButton, ButtonDisplayMode, ButtonHierarchy, ButtonType, ButtonSize, } from '../Buttons';
|
|
5
5
|
import { Typography, TypographySize, TypographyWeight } from '../Typography';
|
|
6
6
|
import { getIconComponent } from '../../utils';
|
|
7
|
-
export const Menu = ({ icon = 'DotsThreeOutline', iconWeight = 'bold', items, style, testKey, size = ButtonSize.xl, hierarchy = ButtonHierarchy.Tertiary, }) => {
|
|
7
|
+
export const Menu = ({ icon = 'DotsThreeOutline', iconWeight = 'bold', items, style, testKey, size = ButtonSize.xl, hierarchy = ButtonHierarchy.Tertiary, onOpenChange, }) => {
|
|
8
8
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
9
9
|
const open = Boolean(anchorEl);
|
|
10
10
|
const handleClick = (event) => {
|
|
11
11
|
setAnchorEl(event.currentTarget);
|
|
12
|
+
onOpenChange?.(true);
|
|
12
13
|
};
|
|
13
14
|
const handleClose = () => {
|
|
14
15
|
setAnchorEl(null);
|
|
16
|
+
onOpenChange?.(false);
|
|
15
17
|
};
|
|
16
18
|
const handleMenuItemClick = (item, event) => {
|
|
17
19
|
handleClose();
|
|
@@ -217,6 +217,8 @@ export type MenuProps = {
|
|
|
217
217
|
size?: ButtonSize;
|
|
218
218
|
/** Hierarchy of the trigger button */
|
|
219
219
|
hierarchy?: ButtonHierarchy;
|
|
220
|
+
/** Called when the menu opens (true) or closes (false) */
|
|
221
|
+
onOpenChange?: (open: boolean) => void;
|
|
220
222
|
};
|
|
221
223
|
/**
|
|
222
224
|
* Check icon color variants
|