@beydesign/storybook 0.2.29 → 0.3.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/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- 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/{Drawer → Navigation/Drawer}/Drawer.d.ts +4 -0
- package/dist/stories/Navigation/Drawer/Drawer.js +81 -0
- package/dist/stories/{Drawer → Navigation/Drawer}/Drawer.stories.js +1 -1
- package/dist/stories/Navigation/Drawer/DrawerBody.d.ts +9 -0
- package/dist/stories/Navigation/Drawer/DrawerBody.js +73 -0
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCard.js +3 -3
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCard.stories.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCardSkeleton.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCardSkeleton.stories.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerNavItem.d.ts +1 -1
- package/dist/stories/Navigation/Drawer/DrawerNavItem.js +22 -0
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerNavItem.stories.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfile.js +3 -3
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfile.stories.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfileSkeleton.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfileSkeleton.stories.js +1 -1
- package/dist/stories/{Drawer → Navigation/Drawer}/index.d.ts +1 -0
- package/dist/stories/{Drawer → Navigation/Drawer}/index.js +1 -0
- package/dist/stories/{Drawer → Navigation/Drawer}/types.d.ts +44 -34
- package/dist/stories/Navigation/Drawer/types.js +7 -0
- package/dist/stories/Navigation/MobileNav.d.ts +15 -0
- package/dist/stories/Navigation/MobileNav.js +97 -0
- package/dist/stories/Navigation/MobileNav.stories.d.ts +25 -0
- package/dist/stories/Navigation/MobileNav.stories.js +65 -0
- package/dist/stories/Navigation/MobileNavBar.js +3 -13
- package/dist/stories/Navigation/MobileNavBar.stories.js +5 -18
- package/dist/stories/Navigation/SettingsPage.stories.d.ts +19 -0
- package/dist/stories/Navigation/SettingsPage.stories.js +75 -0
- package/dist/stories/Navigation/SubNav/SubNav.d.ts +14 -0
- package/dist/stories/Navigation/SubNav/SubNav.js +16 -0
- package/dist/stories/{Settings/SettingsNav.stories.d.ts → Navigation/SubNav/SubNav.stories.d.ts} +3 -3
- package/dist/stories/{Settings/SettingsNav.stories.js → Navigation/SubNav/SubNav.stories.js} +3 -3
- package/dist/stories/Navigation/SubNav/SubNavBody.d.ts +10 -0
- package/dist/stories/Navigation/SubNav/SubNavBody.js +91 -0
- package/dist/stories/Navigation/SubNav/SubNavItem.d.ts +10 -0
- package/dist/stories/Navigation/SubNav/SubNavItem.js +12 -0
- package/dist/stories/Navigation/SubNav/index.d.ts +4 -0
- package/dist/stories/Navigation/SubNav/index.js +4 -0
- package/dist/stories/Navigation/SubNav/types.d.ts +54 -0
- package/dist/stories/Navigation/index.d.ts +3 -0
- package/dist/stories/Navigation/index.js +3 -0
- package/dist/stories/Navigation/internal/NavPanel.d.ts +21 -0
- package/dist/stories/Navigation/internal/NavPanel.js +45 -0
- package/dist/stories/Navigation/internal/NavRow.d.ts +45 -0
- package/dist/stories/Navigation/internal/NavRow.js +79 -0
- package/dist/stories/Navigation/internal/index.d.ts +11 -0
- package/dist/stories/Navigation/internal/index.js +11 -0
- package/dist/stories/Navigation/internal/types.d.ts +71 -0
- package/dist/stories/Navigation/internal/types.js +30 -0
- package/dist/stories/Navigation/navigation.fixtures.d.ts +22 -0
- package/dist/stories/Navigation/navigation.fixtures.js +64 -0
- package/dist/stories/Navigation/types.d.ts +24 -1
- package/dist/stories/UI/Menu.js +3 -1
- package/dist/stories/UI/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/stories/Drawer/Drawer.js +0 -163
- package/dist/stories/Drawer/DrawerNavItem.js +0 -87
- package/dist/stories/Drawer/types.js +0 -29
- package/dist/stories/Settings/SettingsNav.d.ts +0 -10
- package/dist/stories/Settings/SettingsNav.js +0 -97
- package/dist/stories/Settings/SettingsNavItem.d.ts +0 -9
- package/dist/stories/Settings/SettingsNavItem.js +0 -75
- package/dist/stories/Settings/SettingsPage.stories.d.ts +0 -11
- package/dist/stories/Settings/SettingsPage.stories.js +0 -93
- package/dist/stories/Settings/index.d.ts +0 -3
- package/dist/stories/Settings/index.js +0 -3
- package/dist/stories/Settings/types.d.ts +0 -68
- /package/dist/stories/{Drawer → Navigation/Drawer}/Drawer.stories.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCard.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCard.stories.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCardSkeleton.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerCreditsCardSkeleton.stories.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerIcons.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerIcons.js +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerNavItem.stories.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfile.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfile.stories.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfileSkeleton.d.ts +0 -0
- /package/dist/stories/{Drawer → Navigation/Drawer}/DrawerProfileSkeleton.stories.d.ts +0 -0
- /package/dist/stories/{Settings → Navigation/SubNav}/types.js +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,6 @@ export * from './stories/Buttons';
|
|
|
8
8
|
export * from './stories/Typography';
|
|
9
9
|
export * from './stories/Credits';
|
|
10
10
|
export * from './stories/Navigation';
|
|
11
|
-
export * from './stories/Drawer';
|
|
12
|
-
export * from './stories/Settings';
|
|
13
11
|
export * from './stories/Typography';
|
|
14
12
|
export * from './stories/UI';
|
|
15
13
|
export * from './stories/StripeProduct';
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,6 @@ export * from './stories/Buttons';
|
|
|
8
8
|
export * from './stories/Typography';
|
|
9
9
|
export * from './stories/Credits';
|
|
10
10
|
export * from './stories/Navigation';
|
|
11
|
-
export * from './stories/Drawer';
|
|
12
|
-
export * from './stories/Settings';
|
|
13
11
|
export * from './stories/Typography';
|
|
14
12
|
export * from './stories/UI';
|
|
15
13
|
export * from './stories/StripeProduct';
|
|
@@ -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
|
}
|
|
@@ -6,5 +6,9 @@ import { DrawerProps } from './types';
|
|
|
6
6
|
* toggle. Collapse state can be controlled (`collapsed` + `onToggle`) or left
|
|
7
7
|
* uncontrolled (`defaultCollapsed`). Every colour, space and radius resolves to
|
|
8
8
|
* `@beydesign/tokens` CSS variables, so it renders correctly in light and dark.
|
|
9
|
+
*
|
|
10
|
+
* Below the mobile breakpoint there is no room for this beside a settings
|
|
11
|
+
* sub-nav — use `MobileNav`, which renders the same {@link DrawerBody} as one
|
|
12
|
+
* pane of a single overlay.
|
|
9
13
|
*/
|
|
10
14
|
export declare const Drawer: React.FC<DrawerProps>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import styled from '@emotion/styled';
|
|
4
|
+
import { DrawerSize } from './types';
|
|
5
|
+
import { DrawerBody } from './DrawerBody';
|
|
6
|
+
import { NavPanel } from '../internal';
|
|
7
|
+
import { getIconComponent } from '../../../utils';
|
|
8
|
+
const EXPANDED_WIDTH = '238px';
|
|
9
|
+
const COLLAPSED_WIDTH = '68px';
|
|
10
|
+
/** Composed from the semantic `shadow-sm` design token. */
|
|
11
|
+
const SHADOW_SM = 'var(--global-shadows-shadow-sm-offset-x) var(--global-shadows-shadow-sm-offset-y) var(--global-shadows-shadow-sm-blur) var(--global-shadows-shadow-sm-spread) var(--global-shadows-shadow-sm-color)';
|
|
12
|
+
/**
|
|
13
|
+
* Non-clipping outer shell. The toggle lives here (a sibling of the panel) so
|
|
14
|
+
* it can overhang the right edge without being clipped by the panel's
|
|
15
|
+
* `overflow`.
|
|
16
|
+
*/
|
|
17
|
+
const Shell = styled.aside `
|
|
18
|
+
position: relative;
|
|
19
|
+
flex-shrink: 0;
|
|
20
|
+
height: 100vh;
|
|
21
|
+
width: ${({ $collapsed }) => ($collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH)};
|
|
22
|
+
transition: width 0.3s ease-in-out;
|
|
23
|
+
`;
|
|
24
|
+
const ToggleButton = styled.button `
|
|
25
|
+
appearance: none;
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: 52px;
|
|
28
|
+
right: -16px;
|
|
29
|
+
z-index: 2;
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
width: 32px;
|
|
34
|
+
height: 32px;
|
|
35
|
+
padding: 0;
|
|
36
|
+
border: 1px solid var(--color-border-border-subtle);
|
|
37
|
+
border-radius: var(--spacing-tokens-size-in-px-radius-radius-full);
|
|
38
|
+
background-color: var(--color-background-bg-element);
|
|
39
|
+
color: var(--color-text-text-paragraph);
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
box-shadow: ${SHADOW_SM};
|
|
42
|
+
transition: color 0.2s ease-in-out;
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
color: var(--color-text-text-clicable);
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
/** Rotates the chevron smoothly between expanded (◀) and collapsed (▶). */
|
|
49
|
+
const ToggleIcon = styled.span `
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
transform: rotate(${({ $collapsed }) => ($collapsed ? '180deg' : '0deg')});
|
|
52
|
+
transition: transform 0.3s ease-in-out;
|
|
53
|
+
|
|
54
|
+
@media (prefers-reduced-motion: reduce) {
|
|
55
|
+
transition: none;
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
/**
|
|
59
|
+
* Composed application sidebar ("Drawer"): logo header, navigation list,
|
|
60
|
+
* credits card and user-profile footer, with a floating collapse/expand
|
|
61
|
+
* toggle. Collapse state can be controlled (`collapsed` + `onToggle`) or left
|
|
62
|
+
* uncontrolled (`defaultCollapsed`). Every colour, space and radius resolves to
|
|
63
|
+
* `@beydesign/tokens` CSS variables, so it renders correctly in light and dark.
|
|
64
|
+
*
|
|
65
|
+
* Below the mobile breakpoint there is no room for this beside a settings
|
|
66
|
+
* sub-nav — use `MobileNav`, which renders the same {@link DrawerBody} as one
|
|
67
|
+
* pane of a single overlay.
|
|
68
|
+
*/
|
|
69
|
+
export const Drawer = ({ navItems, activeKey, collapsed, defaultCollapsed = false, onToggle, showToggle = true, credits, creditsLoading = false, profile, profileLoading = false, logo, className, style, testId, }) => {
|
|
70
|
+
const isControlled = collapsed !== undefined;
|
|
71
|
+
const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
|
|
72
|
+
const isCollapsed = isControlled ? collapsed : internalCollapsed;
|
|
73
|
+
const drawerSize = isCollapsed ? DrawerSize.Collapsed : DrawerSize.Expanded;
|
|
74
|
+
const handleToggle = () => {
|
|
75
|
+
const next = !isCollapsed;
|
|
76
|
+
if (!isControlled)
|
|
77
|
+
setInternalCollapsed(next);
|
|
78
|
+
onToggle?.(next);
|
|
79
|
+
};
|
|
80
|
+
return (_jsxs(Shell, { "$collapsed": isCollapsed, className: className, style: style, "data-testid": testId, children: [_jsx(NavPanel, { children: _jsx(DrawerBody, { navItems: navItems, activeKey: activeKey, size: drawerSize, credits: credits, creditsLoading: creditsLoading, profile: profile, profileLoading: profileLoading, logo: logo }) }), showToggle && (_jsx(ToggleButton, { type: "button", onClick: handleToggle, "aria-label": isCollapsed ? 'Expand sidebar' : 'Collapse sidebar', children: _jsx(ToggleIcon, { "$collapsed": isCollapsed, children: getIconComponent('CaretLeft', { size: 16, weight: 'bold' }) }) }))] }));
|
|
81
|
+
};
|
|
@@ -17,7 +17,7 @@ const navItems = [
|
|
|
17
17
|
{ key: 'developers', text: 'Developers', icon: 'BracketsCurly' },
|
|
18
18
|
];
|
|
19
19
|
const meta = {
|
|
20
|
-
title: 'Design System/Components/
|
|
20
|
+
title: 'Design System/Components/Navigation/Drawer',
|
|
21
21
|
component: Drawer,
|
|
22
22
|
parameters: {
|
|
23
23
|
layout: 'fullscreen',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DrawerBodyProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* The Drawer's content — logo header, navigation list, credits card and profile
|
|
5
|
+
* footer — without any panel chrome. `Drawer` wraps it in a `NavPanel` beside a
|
|
6
|
+
* collapse toggle; `MobileNav` renders the very same body as the root pane of
|
|
7
|
+
* its overlay, which is why the two never drift apart.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DrawerBody: React.FC<DrawerBodyProps>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
import { DrawerNavItemHierarchy, DrawerNavItemState, DrawerSize, } from './types';
|
|
4
|
+
import { DrawerNavItem } from './DrawerNavItem';
|
|
5
|
+
import { DrawerCreditsCard } from './DrawerCreditsCard';
|
|
6
|
+
import { DrawerCreditsCardSkeleton } from './DrawerCreditsCardSkeleton';
|
|
7
|
+
import { DrawerProfile } from './DrawerProfile';
|
|
8
|
+
import { DrawerProfileSkeleton } from './DrawerProfileSkeleton';
|
|
9
|
+
import { Logo, LogoVariant } from '../../UI';
|
|
10
|
+
const LogoHeader = styled.div `
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: ${({ $collapsed }) => $collapsed ? 'center' : 'flex-start'};
|
|
14
|
+
height: 38px;
|
|
15
|
+
min-height: 38px;
|
|
16
|
+
margin-bottom: 40px;
|
|
17
|
+
`;
|
|
18
|
+
const Nav = styled.nav `
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
flex: 1;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
gap: var(--spacing-tokens-size-in-px-spacing-spacing-2xl, 24px);
|
|
24
|
+
`;
|
|
25
|
+
const NavTop = styled.div `
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
gap: var(--spacing-tokens-size-in-px-spacing-spacing-lg, 12px);
|
|
29
|
+
`;
|
|
30
|
+
const Footer = styled.div `
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: var(--spacing-tokens-size-in-px-spacing-spacing-2xl, 24px);
|
|
34
|
+
`;
|
|
35
|
+
const FooterSlot = styled.div `
|
|
36
|
+
display: flex;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
`;
|
|
39
|
+
const resolveState = (item, activeKey) => {
|
|
40
|
+
if (item.state)
|
|
41
|
+
return item.state;
|
|
42
|
+
if (item.disabled)
|
|
43
|
+
return DrawerNavItemState.Disabled;
|
|
44
|
+
const key = item.key ?? item.text;
|
|
45
|
+
if (activeKey !== undefined && key === activeKey) {
|
|
46
|
+
return DrawerNavItemState.Active;
|
|
47
|
+
}
|
|
48
|
+
return DrawerNavItemState.Inactive;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* The Drawer's content — logo header, navigation list, credits card and profile
|
|
52
|
+
* footer — without any panel chrome. `Drawer` wraps it in a `NavPanel` beside a
|
|
53
|
+
* collapse toggle; `MobileNav` renders the very same body as the root pane of
|
|
54
|
+
* its overlay, which is why the two never drift apart.
|
|
55
|
+
*/
|
|
56
|
+
export const DrawerBody = ({ navItems, activeKey, size = DrawerSize.Expanded, credits, creditsLoading = false, profile, profileLoading = false, logo, onSubNavOpen, }) => {
|
|
57
|
+
const isCollapsed = size === DrawerSize.Collapsed;
|
|
58
|
+
const handleItemClick = (item) => {
|
|
59
|
+
if (item.disabled)
|
|
60
|
+
return;
|
|
61
|
+
if (item.subNav && onSubNavOpen) {
|
|
62
|
+
onSubNavOpen(item);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (item.link) {
|
|
66
|
+
window.location.href = item.link;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
item.onClick?.();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return (_jsxs(_Fragment, { children: [_jsx(LogoHeader, { "$collapsed": isCollapsed, children: _jsx(Logo, { variant: isCollapsed ? LogoVariant.Icon : LogoVariant.Horizontal, color: logo?.color ?? 'var(--color-foreground-fg-brand-logo)', gradient: logo?.gradient, svgUrl: logo?.svgUrl }) }), _jsxs(Nav, { children: [_jsx(NavTop, { children: navItems.map((item) => (_jsx(DrawerNavItem, { text: item.text, icon: item.icon, state: resolveState(item, activeKey), size: size, hierarchy: item.hierarchy ?? DrawerNavItemHierarchy.First, showBadge: item.showBadge, badgeText: item.badgeText, showSubNavCaret: Boolean(item.subNav && onSubNavOpen), onClick: () => handleItemClick(item) }, item.key ?? item.text))) }), (credits || creditsLoading || profile || profileLoading) && (_jsxs(Footer, { children: [(credits || creditsLoading) && (_jsx(FooterSlot, { children: creditsLoading ? (_jsx(DrawerCreditsCardSkeleton, { size: size })) : (_jsx(DrawerCreditsCard, { ...credits, size: size })) })), (profile || profileLoading) && (_jsx(FooterSlot, { children: profileLoading ? (_jsx(DrawerProfileSkeleton, { size: size })) : (profile && _jsx(DrawerProfile, { ...profile, size: size })) }))] }))] })] }));
|
|
73
|
+
};
|