@beydesign/storybook 0.0.84 → 0.0.86
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/Credits/CreditsCard.js +22 -9
- package/dist/stories/Credits/CreditsCard.stories.js +2 -0
- package/dist/stories/Credits/types.d.ts +8 -0
- package/dist/stories/Form/Checkbox.js +1 -1
- package/dist/stories/Form/Dropdown.d.ts +3 -0
- package/dist/stories/Form/Dropdown.js +168 -0
- package/dist/stories/Form/Dropdown.stories.d.ts +6 -0
- package/dist/stories/Form/Dropdown.stories.js +122 -0
- package/dist/stories/Form/FileUpload/FileUploading.js +6 -3
- package/dist/stories/Form/FileUpload/FileUploading.stories.d.ts +2 -0
- package/dist/stories/Form/FileUpload/FileUploading.stories.js +31 -1
- package/dist/stories/Form/index.d.ts +1 -0
- package/dist/stories/Form/index.js +1 -0
- package/dist/stories/Form/types.d.ts +59 -1
- package/dist/stories/Form/types.js +16 -0
- package/dist/stories/Typography/Typography.stories.js +7 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import styled from '@emotion/styled';
|
|
3
4
|
import { CreditsCardSize } from './types';
|
|
4
5
|
import { Typography, TypographySize, TypographyWeight } from '../Typography';
|
|
@@ -9,7 +10,9 @@ const StyledCard = styled.div `
|
|
|
9
10
|
flex-direction: column;
|
|
10
11
|
gap: ${({ $size }) => ($size === CreditsCardSize.Collapsed ? '8px' : '16px')};
|
|
11
12
|
padding: ${({ $size }) => $size === CreditsCardSize.Collapsed ? '20px 16px' : '24px'};
|
|
12
|
-
background-color:
|
|
13
|
+
background-color: ${({ $warning }) => $warning
|
|
14
|
+
? 'var(--primitives-desktop-primary-red-50)'
|
|
15
|
+
: 'var(--colors-light-background-bg-card-highlight)'};
|
|
13
16
|
border: 1px solid var(--colors-light-border-border-default);
|
|
14
17
|
border-radius: var(--spacing-tokens-size-in-px-spacing-spacing-md);
|
|
15
18
|
padding: ${({ $collapsed }) => $collapsed
|
|
@@ -35,13 +38,23 @@ const TextWrapper = styled.span `
|
|
|
35
38
|
display: inline-block;
|
|
36
39
|
white-space: nowrap;
|
|
37
40
|
`;
|
|
38
|
-
export const CreditsCard = ({ size = CreditsCardSize.Expanded, className, maxCredits = 1, usedCredits = 0, onUpgradeClick, creditInfoText = '1 Credit = 1 min video', }) => {
|
|
41
|
+
export const CreditsCard = ({ size = CreditsCardSize.Expanded, className, maxCredits = 1, usedCredits = 0, onUpgradeClick, creditInfoText = '1 Credit = 1 min video', overUsageEnabled = false, overUsedCredits = 0, }) => {
|
|
39
42
|
const isCollapsed = size === CreditsCardSize.Collapsed;
|
|
40
|
-
|
|
43
|
+
const creditsLimitReached = usedCredits >= maxCredits;
|
|
44
|
+
const case1 = overUsageEnabled && overUsedCredits > 0; // if over usage is enabled and over used credits are greater than 0
|
|
45
|
+
const case2 = case1 || !creditsLimitReached; // if case 1 is true or credits limit is not reached
|
|
46
|
+
const case3 = !overUsageEnabled && creditsLimitReached; // if over usage is not enabled and credits limit is reached
|
|
47
|
+
return (_jsxs(StyledCard, { "$collapsed": isCollapsed, "$size": size, className: className, "$warning": case3, children: [!isCollapsed &&
|
|
41
48
|
maxCredits !== undefined &&
|
|
42
|
-
usedCredits !== undefined && (_jsxs(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
usedCredits !== undefined && (_jsxs(React.Fragment, { children: [_jsxs(CreditRow, { style: {
|
|
50
|
+
gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)',
|
|
51
|
+
}, children: [case2 && (_jsxs(Box, { gap: "2px", display: "flex", flexDirection: "row", children: [_jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: "My Credits:" }) }), _jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: `${usedCredits}/` }) }), _jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-paragraph)", children: `${maxCredits}` }) })] })), case3 && (_jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: "Credits Limit Reached" }) })), _jsx(MainButton, { text: "Upgrade", hierarchy: ButtonHierarchy.TetriaryColor, size: ButtonSize.md, style: { padding: '0' }, onClick: () => {
|
|
52
|
+
if (onUpgradeClick) {
|
|
53
|
+
onUpgradeClick();
|
|
54
|
+
}
|
|
55
|
+
} })] }), case1 && (_jsx(CreditRow, { children: _jsx(Box, { display: "flex", flexDirection: "row", children: _jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: `Overused: ${overUsedCredits}` }) }) }) })), _jsx(CreditRow, { style: { justifyContent: 'end' }, children: _jsx(Box, { display: "flex", flexDirection: "row", children: _jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextXS, weight: TypographyWeight.Regular, color: "var(--colors-light-text-text-subtle)", children: creditInfoText }) }) }) })] })), isCollapsed && maxCredits !== undefined && usedCredits !== undefined && (_jsxs(Box, { display: "flex", flexDirection: "column", gap: "var(--spacing-tokens-size-in-px-spacing-spacing-md)", alignItems: "center", justifyContent: "center", children: [case2 && (_jsx(CreditRow, { "$collapsed": true, children: _jsxs(Box, { display: "flex", flexDirection: "row", gap: "2px", children: [_jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextM, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: `${usedCredits}/` }) }), _jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextM, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-paragraph)", children: `${maxCredits}` }) })] }) })), case3 && (_jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextM, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", textStyle: { textOverflow: 'ellipsis' }, title: "Credits Limit Reached", children: "Credits..." }) })), case1 && (_jsx(TextWrapper, { children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, color: "var(--colors-light-text-text-title)", children: `${overUsedCredits}` }) })), _jsx(Box, { onClick: (e) => e.stopPropagation(), children: _jsx(MainButton, { text: "Upgrade", hierarchy: ButtonHierarchy.TetriaryColor, size: ButtonSize.md, style: { padding: '0' }, onClick: () => {
|
|
56
|
+
if (onUpgradeClick) {
|
|
57
|
+
onUpgradeClick();
|
|
58
|
+
}
|
|
59
|
+
} }) })] }))] }));
|
|
47
60
|
};
|
|
@@ -32,4 +32,12 @@ export interface CreditsCardProps {
|
|
|
32
32
|
* Text explaining credit usage (e.g., "1 Credit = 1 min video")
|
|
33
33
|
*/
|
|
34
34
|
creditInfoText?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether to enable over usage
|
|
37
|
+
*/
|
|
38
|
+
overUsageEnabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Over used credits
|
|
41
|
+
*/
|
|
42
|
+
overUsedCredits?: number;
|
|
35
43
|
}
|
|
@@ -61,5 +61,5 @@ export const Checkbox = ({ type = CheckboxType.Checkbox, label, checked, disable
|
|
|
61
61
|
backgroundColor: 'transparent',
|
|
62
62
|
transition: 'all 0.2s ease-in-out',
|
|
63
63
|
},
|
|
64
|
-
} })) : null, _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, children: label })] }));
|
|
64
|
+
} })) : null, label && (_jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Medium, children: label }))] }));
|
|
65
65
|
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
|
+
import { DropdownType } from './types';
|
|
4
|
+
import { Box, ClickAwayListener, Popper } from '@mui/material';
|
|
5
|
+
import { Typography, TypographySize, TypographyWeight } from '../Typography';
|
|
6
|
+
import { getIconComponent } from '../../utils';
|
|
7
|
+
import { Checkbox } from './Checkbox';
|
|
8
|
+
export const Dropdown = ({ disabled = false, placeholder = 'Select an option', label = 'Select', showLeadingIcon = false, leadingIcon = 'List', showClear = true, options, required = false, showCheckboxes = false, showTicks = true, ...props }) => {
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
11
|
+
const anchorRef = useRef(null);
|
|
12
|
+
const optionsContainerRef = useRef(null);
|
|
13
|
+
const value = useMemo(() => {
|
|
14
|
+
if (props.type === DropdownType.SingleSelect) {
|
|
15
|
+
return props.value;
|
|
16
|
+
}
|
|
17
|
+
return Array.isArray(props.value) ? props.value.join(', ') : '';
|
|
18
|
+
}, [props.type, props.value]);
|
|
19
|
+
const handleOptionSelect = useCallback((option) => {
|
|
20
|
+
if (props.type === DropdownType.SingleSelect) {
|
|
21
|
+
props.onChange(option);
|
|
22
|
+
setOpen(false);
|
|
23
|
+
}
|
|
24
|
+
else if (Array.isArray(props.value)) {
|
|
25
|
+
const newValue = props.value.includes(option)
|
|
26
|
+
? props.value.filter((item) => item !== option)
|
|
27
|
+
: [...props.value, option];
|
|
28
|
+
props.onChange(newValue);
|
|
29
|
+
}
|
|
30
|
+
}, [props]);
|
|
31
|
+
const handleClear = (e) => {
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
if (props.type === DropdownType.SingleSelect) {
|
|
34
|
+
props.onChange('');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
props.onChange([]);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const handleKeyDown = (e) => {
|
|
41
|
+
if (disabled)
|
|
42
|
+
return;
|
|
43
|
+
switch (e.key) {
|
|
44
|
+
case 'Enter':
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
if (open) {
|
|
47
|
+
handleOptionSelect(options[highlightedIndex]);
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case ' ':
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
setOpen((prev) => !prev);
|
|
53
|
+
break;
|
|
54
|
+
case 'Escape':
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
setOpen(false);
|
|
57
|
+
break;
|
|
58
|
+
case 'ArrowDown':
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
if (!open) {
|
|
61
|
+
setOpen(true);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
setHighlightedIndex((prev) => prev < options.length - 1 ? prev + 1 : 0);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
case 'ArrowUp':
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
if (!open) {
|
|
70
|
+
setOpen(true);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
setHighlightedIndex((prev) => prev > 0 ? prev - 1 : options.length - 1);
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
case 'Tab':
|
|
77
|
+
if (open) {
|
|
78
|
+
setOpen(false);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// Select highlighted option on Enter
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const handleKeyPress = (e) => {
|
|
86
|
+
if (open &&
|
|
87
|
+
e.key === 'Enter' &&
|
|
88
|
+
highlightedIndex >= 0 &&
|
|
89
|
+
highlightedIndex < options.length &&
|
|
90
|
+
!disabled) {
|
|
91
|
+
handleOptionSelect(options[highlightedIndex]);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
window.addEventListener('keydown', handleKeyPress);
|
|
95
|
+
return () => {
|
|
96
|
+
window.removeEventListener('keydown', handleKeyPress);
|
|
97
|
+
};
|
|
98
|
+
}, [open, highlightedIndex, options, handleOptionSelect, disabled]);
|
|
99
|
+
// Scroll to highlighted option
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (open && highlightedIndex >= 0 && optionsContainerRef.current) {
|
|
102
|
+
const highlightedElement = optionsContainerRef.current.children[highlightedIndex];
|
|
103
|
+
if (highlightedElement) {
|
|
104
|
+
highlightedElement.scrollIntoView({ block: 'nearest' });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}, [highlightedIndex, open]);
|
|
108
|
+
const isOptionSelected = (option) => {
|
|
109
|
+
if (props.type === DropdownType.SingleSelect) {
|
|
110
|
+
return props.value === option;
|
|
111
|
+
}
|
|
112
|
+
return Array.isArray(props.value) && props.value.includes(option);
|
|
113
|
+
};
|
|
114
|
+
return (_jsx(ClickAwayListener, { onClickAway: () => setOpen(false), children: _jsxs(Box, { display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', position: 'relative', width: "100%", minWidth: '300px', children: [_jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, textStyle: { textAlign: 'left' }, required: required, children: label }), _jsxs(Box, { ref: anchorRef, display: 'flex', flexDirection: 'row', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', alignItems: 'center', justifyContent: 'center', border: `1px solid ${open
|
|
115
|
+
? 'var(--colors-light-border-border-component-active)'
|
|
116
|
+
: 'var(--colors-light-border-border-component)'}`, borderRadius: '4px', bgcolor: disabled
|
|
117
|
+
? 'var(--primitives-desktop-primary-gray-25)'
|
|
118
|
+
: 'var(--primitives-desktop-primary-white-100)', position: 'relative', onClick: () => !disabled && setOpen((prev) => !prev), onKeyDown: handleKeyDown, tabIndex: disabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": open, "aria-disabled": disabled, role: "combobox", children: [showLeadingIcon &&
|
|
119
|
+
getIconComponent(leadingIcon, {
|
|
120
|
+
width: '24px',
|
|
121
|
+
height: '24px',
|
|
122
|
+
color: 'var(--colors-light-foreground-fg-secondary)',
|
|
123
|
+
'aria-hidden': 'true',
|
|
124
|
+
}), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, textStyle: { flexGrow: 1, textAlign: 'left' }, color: value
|
|
125
|
+
? 'var(--colors-light-text-text-title)'
|
|
126
|
+
: 'var(--colors-light-text-text-placeholder)', children: value || placeholder }), !disabled &&
|
|
127
|
+
showClear &&
|
|
128
|
+
value &&
|
|
129
|
+
getIconComponent('X', {
|
|
130
|
+
width: '24px',
|
|
131
|
+
height: '24px',
|
|
132
|
+
color: 'var(--colors-light-foreground-fg-secondary)',
|
|
133
|
+
onClick: handleClear,
|
|
134
|
+
'aria-label': 'Clear selection',
|
|
135
|
+
role: 'button',
|
|
136
|
+
tabIndex: 0,
|
|
137
|
+
onKeyDown: (e) => {
|
|
138
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
handleClear(e);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
}), !disabled &&
|
|
144
|
+
getIconComponent(open ? 'CaretUp' : 'CaretDown', {
|
|
145
|
+
width: '24px',
|
|
146
|
+
height: '24px',
|
|
147
|
+
color: 'var(--colors-light-foreground-fg-secondary)',
|
|
148
|
+
'aria-hidden': 'true',
|
|
149
|
+
})] }), _jsx(Popper, { open: open, anchorEl: anchorRef.current, placement: "bottom-start", style: { width: anchorRef.current?.offsetWidth, zIndex: 1300 }, children: _jsx(Box, { ref: optionsContainerRef, bgcolor: 'var(--primitives-desktop-primary-white-100)', borderRadius: '4px', width: '100%', maxHeight: '200px', overflow: 'auto', boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)', mt: '4px', role: "listbox", sx: {
|
|
150
|
+
border: '1px solid var(--colors-light-border-border-component)',
|
|
151
|
+
}, children: options.length === 0 ? (_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" }) })) : (options.map((option, index) => (_jsxs(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', padding: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', onClick: () => handleOptionSelect(option), onMouseEnter: () => setHighlightedIndex(index), sx: {
|
|
152
|
+
cursor: 'pointer',
|
|
153
|
+
backgroundColor: highlightedIndex === index
|
|
154
|
+
? 'var(--primitives-desktop-primary-gray-25)'
|
|
155
|
+
: isOptionSelected(option)
|
|
156
|
+
? 'var(--primitives-desktop-primary-gray-10)'
|
|
157
|
+
: 'transparent',
|
|
158
|
+
'&:hover': {
|
|
159
|
+
backgroundColor: 'var(--colors-light-background-bg-card-highlight)',
|
|
160
|
+
},
|
|
161
|
+
}, role: "option", "aria-selected": isOptionSelected(option), children: [_jsxs(Box, { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-xs)', children: [showCheckboxes && (_jsx(Checkbox, { checked: isOptionSelected(option), onChange: () => handleOptionSelect(option), style: { margin: 0, padding: 0 } })), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: "var(--colors-light-text-text-title)", children: option })] }), showTicks &&
|
|
162
|
+
isOptionSelected(option) &&
|
|
163
|
+
getIconComponent('Check', {
|
|
164
|
+
width: '16px',
|
|
165
|
+
height: '16px',
|
|
166
|
+
color: 'var(--colors-light-foreground-fg-brand-primary)',
|
|
167
|
+
})] }, option)))) }) })] }) }));
|
|
168
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Dropdown } from './Dropdown';
|
|
2
|
+
import { DropdownType } from './types';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Design System/Components/Form/Dropdown',
|
|
5
|
+
component: Dropdown,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'centered',
|
|
8
|
+
design: {
|
|
9
|
+
type: 'figspec',
|
|
10
|
+
url: 'https://www.figma.com/design/mIhjz2yJjcpLlIqw6oUivt/Beyond-Presence?node-id=4501-25356&t=XsmO3ZzXQ9rb1lu5-1',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: {
|
|
15
|
+
options: {
|
|
16
|
+
control: 'select',
|
|
17
|
+
description: 'The options to display in the dropdown',
|
|
18
|
+
table: {
|
|
19
|
+
type: { summary: 'string[]' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
value: {
|
|
23
|
+
control: 'text',
|
|
24
|
+
description: 'The value of the selected option',
|
|
25
|
+
table: {
|
|
26
|
+
type: { summary: 'string' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
onChange: {
|
|
30
|
+
description: 'The onChange handler for the selected option',
|
|
31
|
+
table: {
|
|
32
|
+
type: { summary: 'function' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
disabled: {
|
|
36
|
+
control: 'boolean',
|
|
37
|
+
description: 'Whether the autocomplete is disabled',
|
|
38
|
+
table: {
|
|
39
|
+
type: { summary: 'boolean' },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
placeholder: {
|
|
43
|
+
control: 'text',
|
|
44
|
+
description: 'The placeholder of the autocomplete',
|
|
45
|
+
table: {
|
|
46
|
+
type: { summary: 'string' },
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
type: {
|
|
50
|
+
control: 'select',
|
|
51
|
+
description: 'The type of the dropdown',
|
|
52
|
+
options: Object.values(DropdownType),
|
|
53
|
+
table: {
|
|
54
|
+
defaultValue: { summary: DropdownType.SingleSelect },
|
|
55
|
+
type: { summary: 'string' },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
label: {
|
|
59
|
+
control: 'text',
|
|
60
|
+
description: 'The label of the dropdown',
|
|
61
|
+
table: {
|
|
62
|
+
type: { summary: 'string' },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
leadingIcon: {
|
|
66
|
+
control: 'select',
|
|
67
|
+
description: 'The leading icon of the dropdown',
|
|
68
|
+
options: ['Cactus', 'MagnifyingGlass', 'User', 'Check', 'X'],
|
|
69
|
+
table: {
|
|
70
|
+
type: { summary: 'string' },
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
required: {
|
|
74
|
+
control: 'boolean',
|
|
75
|
+
description: 'Whether the dropdown is required',
|
|
76
|
+
table: {
|
|
77
|
+
type: { summary: 'boolean' },
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
showClear: {
|
|
81
|
+
control: 'boolean',
|
|
82
|
+
description: 'Whether to show the clear button',
|
|
83
|
+
table: {
|
|
84
|
+
type: { summary: 'boolean' },
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
showLeadingIcon: {
|
|
88
|
+
control: 'boolean',
|
|
89
|
+
description: 'Whether to show the leading icon',
|
|
90
|
+
table: {
|
|
91
|
+
type: { summary: 'boolean' },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
export default meta;
|
|
97
|
+
export const Default = {
|
|
98
|
+
args: {
|
|
99
|
+
options: [
|
|
100
|
+
'Option 1',
|
|
101
|
+
'Option 2',
|
|
102
|
+
'Option 3',
|
|
103
|
+
'Option 4',
|
|
104
|
+
'Option 5',
|
|
105
|
+
'Option 6',
|
|
106
|
+
'Option 7',
|
|
107
|
+
'Option 8',
|
|
108
|
+
'Option 9',
|
|
109
|
+
'Option 10',
|
|
110
|
+
],
|
|
111
|
+
value: 'Option 1',
|
|
112
|
+
onChange: () => { },
|
|
113
|
+
type: DropdownType.SingleSelect,
|
|
114
|
+
placeholder: 'Select an option',
|
|
115
|
+
label: 'Select',
|
|
116
|
+
leadingIcon: 'List',
|
|
117
|
+
disabled: false,
|
|
118
|
+
showClear: true,
|
|
119
|
+
showLeadingIcon: true,
|
|
120
|
+
required: false,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
|
-
import { FileUploadingStatus } from '../types';
|
|
3
|
+
import { FileUploadingStatus, FileUploadingProgressMode, } from '../types';
|
|
4
4
|
import { Box } from '@mui/material';
|
|
5
5
|
import { Typography, TypographySize, TypographyWeight } from '../../Typography';
|
|
6
6
|
import { getIconComponent } from '../../../utils';
|
|
7
7
|
import { Player } from '@lottiefiles/react-lottie-player';
|
|
8
8
|
import loadingAnimation from '../../../assets/animations/loading-animation.json';
|
|
9
|
-
|
|
9
|
+
import { ProgressIndicator, ProgressIndicatorMode } from '../../UI';
|
|
10
|
+
export const FileUploading = ({ uploadProgress, uploadingStatus, progressMode = FileUploadingProgressMode.Animation, sx, onCancel, onRetry, fileName, showCancel, showRetry, }) => {
|
|
10
11
|
const isUploading = uploadingStatus === FileUploadingStatus.Uploading;
|
|
11
12
|
const isSuccess = uploadingStatus === FileUploadingStatus.Success;
|
|
12
13
|
const isError = uploadingStatus === FileUploadingStatus.Error;
|
|
14
|
+
const isPercentageProgress = progressMode === FileUploadingProgressMode.Percentage;
|
|
15
|
+
const isAnimationProgress = progressMode === FileUploadingProgressMode.Animation;
|
|
13
16
|
const fileExtension = fileName.split('.').pop();
|
|
14
17
|
const getFileIcon = () => {
|
|
15
18
|
if (fileExtension?.toLowerCase() === 'pdf')
|
|
@@ -42,5 +45,5 @@ export const FileUploading = ({ uploadingStatus, sx, onCancel, onRetry, fileName
|
|
|
42
45
|
width: '24px',
|
|
43
46
|
height: '24px',
|
|
44
47
|
color: 'var(--colors-light-foreground-fg-success)',
|
|
45
|
-
})] })] }), _jsxs(Box, { display: 'flex', flexDirection: '
|
|
48
|
+
})] })] }), _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 && (_jsx(ProgressIndicator, { currentValue: uploadProgress || 0, maxValue: 100, mode: ProgressIndicatorMode.Percentage, style: { width: '100%', height: '100%' } })), isError && (_jsxs(Fragment, { children: [_jsx(Typography, { size: TypographySize.TextXS, weight: TypographyWeight.Regular, color: 'var(--colors-light-text-text-error)', children: "Upload failed, please try again." }), showRetry && onRetry && (_jsx(Box, { onClick: onRetry, style: { cursor: 'pointer' }, children: _jsx(Typography, { size: TypographySize.TextXS, weight: TypographyWeight.SemiBold, color: 'var(--colors-light-text-text-error)', children: "Try again" }) }))] }))] })] }));
|
|
46
49
|
};
|
|
@@ -4,5 +4,7 @@ declare const meta: Meta<typeof FileUploading>;
|
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof FileUploading>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
|
+
export declare const PercentageProgress: Story;
|
|
8
|
+
export declare const AnimationProgress: Story;
|
|
7
9
|
export declare const Success: Story;
|
|
8
10
|
export declare const Error: Story;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FileUploading } from './FileUploading';
|
|
2
|
-
import { FileUploadingStatus } from '../types';
|
|
2
|
+
import { FileUploadingStatus, FileUploadingProgressMode } from '../types';
|
|
3
3
|
const meta = {
|
|
4
4
|
title: 'Design System/Components/Form/FileUpload/FileUploading',
|
|
5
5
|
component: FileUploading,
|
|
@@ -24,6 +24,17 @@ const meta = {
|
|
|
24
24
|
description: 'The status of the file upload',
|
|
25
25
|
table: { type: { summary: 'FileUploadingStatus' } },
|
|
26
26
|
},
|
|
27
|
+
uploadProgress: {
|
|
28
|
+
control: 'number',
|
|
29
|
+
description: 'The progress of the file upload',
|
|
30
|
+
table: { type: { summary: 'number' } },
|
|
31
|
+
},
|
|
32
|
+
progressMode: {
|
|
33
|
+
control: 'select',
|
|
34
|
+
options: Object.values(FileUploadingProgressMode),
|
|
35
|
+
description: 'The mode of the file upload progress',
|
|
36
|
+
table: { type: { summary: 'ProgressMode' } },
|
|
37
|
+
},
|
|
27
38
|
showCancel: {
|
|
28
39
|
control: 'boolean',
|
|
29
40
|
description: 'Whether to show the cancel button',
|
|
@@ -60,6 +71,25 @@ export const Default = {
|
|
|
60
71
|
showRetry: true,
|
|
61
72
|
},
|
|
62
73
|
};
|
|
74
|
+
export const PercentageProgress = {
|
|
75
|
+
args: {
|
|
76
|
+
fileName: 'test.pdf',
|
|
77
|
+
uploadingStatus: FileUploadingStatus.Uploading,
|
|
78
|
+
showCancel: true,
|
|
79
|
+
showRetry: true,
|
|
80
|
+
progressMode: FileUploadingProgressMode.Percentage,
|
|
81
|
+
uploadProgress: 50,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export const AnimationProgress = {
|
|
85
|
+
args: {
|
|
86
|
+
fileName: 'test.pdf',
|
|
87
|
+
uploadingStatus: FileUploadingStatus.Uploading,
|
|
88
|
+
showCancel: true,
|
|
89
|
+
showRetry: true,
|
|
90
|
+
progressMode: FileUploadingProgressMode.Animation,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
63
93
|
export const Success = {
|
|
64
94
|
args: {
|
|
65
95
|
fileName: 'test.pdf',
|
|
@@ -110,7 +110,7 @@ export type CheckboxProps = {
|
|
|
110
110
|
/** Type variant of the checkbox */
|
|
111
111
|
type?: CheckboxType;
|
|
112
112
|
/** Label of the checkbox */
|
|
113
|
-
label
|
|
113
|
+
label?: string;
|
|
114
114
|
/** Whether the checkbox is checked */
|
|
115
115
|
checked?: boolean;
|
|
116
116
|
/** Whether the checkbox is disabled */
|
|
@@ -165,12 +165,23 @@ export declare enum FileUploadingStatus {
|
|
|
165
165
|
Success = "Success",
|
|
166
166
|
Error = "Error"
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Progress mode variants
|
|
170
|
+
*/
|
|
171
|
+
export declare enum FileUploadingProgressMode {
|
|
172
|
+
Percentage = "Percentage",
|
|
173
|
+
Animation = "Animation"
|
|
174
|
+
}
|
|
168
175
|
/**
|
|
169
176
|
* File uploading component props
|
|
170
177
|
*/
|
|
171
178
|
export interface FileUploadingProps {
|
|
172
179
|
/** Status of the file uploading */
|
|
173
180
|
uploadingStatus: FileUploadingStatus;
|
|
181
|
+
/** Progress mode of the file uploading */
|
|
182
|
+
progressMode?: FileUploadingProgressMode;
|
|
183
|
+
/** Progress of the file uploading */
|
|
184
|
+
uploadProgress?: number;
|
|
174
185
|
/** Style of the file uploading */
|
|
175
186
|
sx?: SxProps<Theme>;
|
|
176
187
|
/** Whether to show the cancel button */
|
|
@@ -202,3 +213,50 @@ export interface AutoCompleteProps {
|
|
|
202
213
|
/** The onFocus handler for the autocomplete */
|
|
203
214
|
onFocus?: () => void;
|
|
204
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Dropdown type variants
|
|
218
|
+
*/
|
|
219
|
+
export declare enum DropdownType {
|
|
220
|
+
SingleSelect = "SingleSelect",
|
|
221
|
+
MultiSelect = "MultiSelect"
|
|
222
|
+
}
|
|
223
|
+
type SingleSelectDropdownProps = {
|
|
224
|
+
/** The value of the selected option */
|
|
225
|
+
value: string;
|
|
226
|
+
/** The onChange handler for the selected option */
|
|
227
|
+
onChange: (value: string) => void;
|
|
228
|
+
/** The type of the dropdown */
|
|
229
|
+
type: DropdownType.SingleSelect;
|
|
230
|
+
};
|
|
231
|
+
type MultiSelectDropdownProps = {
|
|
232
|
+
/** The value of the selected options */
|
|
233
|
+
value: string[];
|
|
234
|
+
/** The onChange handler for the selected options */
|
|
235
|
+
onChange: (value: string[]) => void;
|
|
236
|
+
/** The type of the dropdown */
|
|
237
|
+
type: DropdownType.MultiSelect;
|
|
238
|
+
};
|
|
239
|
+
type DropdownBaseProps = SingleSelectDropdownProps | MultiSelectDropdownProps;
|
|
240
|
+
export type DropdownProps = DropdownBaseProps & {
|
|
241
|
+
/** The label of the dropdown */
|
|
242
|
+
label?: string;
|
|
243
|
+
/** The options to display in the dropdown */
|
|
244
|
+
options: string[];
|
|
245
|
+
/** The placeholder of the dropdown */
|
|
246
|
+
placeholder?: string;
|
|
247
|
+
/** Whether the dropdown is disabled */
|
|
248
|
+
disabled?: boolean;
|
|
249
|
+
/** Whether the dropdown is required */
|
|
250
|
+
required?: boolean;
|
|
251
|
+
/** Whether to show the leading icon */
|
|
252
|
+
showLeadingIcon?: boolean;
|
|
253
|
+
/** The leading icon of the dropdown */
|
|
254
|
+
leadingIcon?: IconName;
|
|
255
|
+
/** Whether to show the clear button */
|
|
256
|
+
showClear?: boolean;
|
|
257
|
+
/** Whether to show the checkboxes */
|
|
258
|
+
showCheckboxes?: boolean;
|
|
259
|
+
/** Whether to show the ticks */
|
|
260
|
+
showTicks?: boolean;
|
|
261
|
+
};
|
|
262
|
+
export {};
|
|
@@ -28,3 +28,19 @@ export var FileUploadingStatus;
|
|
|
28
28
|
FileUploadingStatus["Success"] = "Success";
|
|
29
29
|
FileUploadingStatus["Error"] = "Error";
|
|
30
30
|
})(FileUploadingStatus || (FileUploadingStatus = {}));
|
|
31
|
+
/**
|
|
32
|
+
* Progress mode variants
|
|
33
|
+
*/
|
|
34
|
+
export var FileUploadingProgressMode;
|
|
35
|
+
(function (FileUploadingProgressMode) {
|
|
36
|
+
FileUploadingProgressMode["Percentage"] = "Percentage";
|
|
37
|
+
FileUploadingProgressMode["Animation"] = "Animation";
|
|
38
|
+
})(FileUploadingProgressMode || (FileUploadingProgressMode = {}));
|
|
39
|
+
/**
|
|
40
|
+
* Dropdown type variants
|
|
41
|
+
*/
|
|
42
|
+
export var DropdownType;
|
|
43
|
+
(function (DropdownType) {
|
|
44
|
+
DropdownType["SingleSelect"] = "SingleSelect";
|
|
45
|
+
DropdownType["MultiSelect"] = "MultiSelect";
|
|
46
|
+
})(DropdownType || (DropdownType = {}));
|