merge: remove MUI/styled-components from BasePanel — cc- CSS classes (P2a)
This commit is contained in:
commit
f1c1a72f44
@ -1,31 +1,6 @@
|
|||||||
import React, { useEffect, useRef, useMemo } from 'react';
|
import React, { useEffect, useRef, useMemo, useState } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { TldrawUiButton } from '@tldraw/tldraw';
|
import { TldrawUiButton } from '@tldraw/tldraw';
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
styled,
|
|
||||||
ThemeProvider,
|
|
||||||
createTheme,
|
|
||||||
useMediaQuery
|
|
||||||
} from '@mui/material';
|
|
||||||
import {
|
|
||||||
PushPin as PushPinIcon,
|
|
||||||
PushPinOutlined as PushPinOutlinedIcon,
|
|
||||||
ExpandMore as ExpandMoreIcon,
|
|
||||||
Category as ShapesIcon,
|
|
||||||
Slideshow as SlidesIcon,
|
|
||||||
YouTube as YouTubeIcon,
|
|
||||||
AccountTree as GraphIcon,
|
|
||||||
Search as SearchIcon,
|
|
||||||
Navigation as NavigationIcon,
|
|
||||||
Save as NodeIcon,
|
|
||||||
Assignment as ExamIcon,
|
|
||||||
Mic as MicIcon
|
|
||||||
} from '@mui/icons-material';
|
|
||||||
import { CCShapesPanel } from './CCShapesPanel';
|
import { CCShapesPanel } from './CCShapesPanel';
|
||||||
import { CCSlidesPanel } from './CCSlidesPanel';
|
import { CCSlidesPanel } from './CCSlidesPanel';
|
||||||
import { CCFilesPanel } from './CCFilesPanel';
|
import { CCFilesPanel } from './CCFilesPanel';
|
||||||
@ -33,9 +8,9 @@ import { CCCabinetsPanel } from './CCCabinetsPanel';
|
|||||||
import { CCYoutubePanel } from './CCYoutubePanel';
|
import { CCYoutubePanel } from './CCYoutubePanel';
|
||||||
import { CCGraphPanel } from './CCGraphPanel';
|
import { CCGraphPanel } from './CCGraphPanel';
|
||||||
import { CCExamMarkerPanel } from './CCExamMarkerPanel';
|
import { CCExamMarkerPanel } from './CCExamMarkerPanel';
|
||||||
import { CCSearchPanel } from './CCSearchPanel'
|
import { CCSearchPanel } from './CCSearchPanel';
|
||||||
import { CCGraphNavPanel } from './navigation/CCGraphNavPanel'
|
import { CCGraphNavPanel } from './navigation/CCGraphNavPanel';
|
||||||
import { CCTranscriptionPanel } from './CCTranscriptionPanel'
|
import { CCTranscriptionPanel } from './CCTranscriptionPanel';
|
||||||
import { PANEL_DIMENSIONS, Z_INDICES } from './panel-styles';
|
import { PANEL_DIMENSIONS, Z_INDICES } from './panel-styles';
|
||||||
import './panel.css';
|
import './panel.css';
|
||||||
// import { CCNavigationPanel } from './navigation/CCNavigationPanel';
|
// import { CCNavigationPanel } from './navigation/CCNavigationPanel';
|
||||||
@ -78,45 +53,102 @@ interface BasePanelProps {
|
|||||||
onMenuOpenChange?: (open: boolean) => void;
|
onMenuOpenChange?: (open: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PanelTypeButton = styled(Button)(() => ({
|
function getIconSvg(panelId: PanelType, size = '1.25rem') {
|
||||||
textTransform: 'none',
|
const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
|
||||||
padding: '6px 12px',
|
switch (panelId) {
|
||||||
gap: '8px',
|
case 'cabinets':
|
||||||
backgroundColor: 'var(--color-panel)',
|
return (
|
||||||
color: 'var(--color-text)',
|
<svg {...common}>
|
||||||
border: '1px solid transparent',
|
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||||
transition: 'border-color 200ms ease',
|
<polyline points="9 22 9 12 15 12 15 22" />
|
||||||
justifyContent: 'space-between',
|
</svg>
|
||||||
minWidth: '200px',
|
);
|
||||||
'&:hover': {
|
case 'transcription':
|
||||||
backgroundColor: 'var(--color-panel)',
|
return (
|
||||||
borderColor: 'var(--color-text)',
|
<svg {...common}>
|
||||||
},
|
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
|
||||||
'& .MuiSvgIcon-root': {
|
<path d="M19 10v2a7 7 0 0 1-14 0v-2" />
|
||||||
fontSize: '1.25rem',
|
<line x1="12" y1="19" x2="12" y2="23" />
|
||||||
color: 'inherit',
|
<line x1="8" y1="23" x2="6" y2="21" />
|
||||||
|
<line x1="16" y1="23" x2="14" y2="21" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'cc-shapes':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<rect x="3" y="3" width="7" height="7" />
|
||||||
|
<rect x="14" y="3" width="7" height="7" />
|
||||||
|
<rect x="14" y="14" width="7" height="7" />
|
||||||
|
<rect x="3" y="14" width="7" height="7" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'slides':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<rect x="2" y="3" width="13" height="18" rx="2" />
|
||||||
|
<path d="M15 8h4l3 3v7h-7V8z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'youtube':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<rect x="2" y="4" width="20" height="16" rx="4" />
|
||||||
|
<polygon points="10 8 16 12 10 16 10 8" fill="currentColor" stroke="none" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'graph':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<circle cx="18" cy="5" r="3" />
|
||||||
|
<circle cx="6" cy="12" r="3" />
|
||||||
|
<circle cx="18" cy="19" r="3" />
|
||||||
|
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
|
||||||
|
<line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'search':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<circle cx="11" cy="11" r="8" />
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'navigation':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<polygon points="3 11 22 2 13 21 11 13 3 11" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'node-snapshot':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
case 'exam-marker':
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||||
|
<polyline points="14 2 14 8 20 8" />
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13" />
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17" />
|
||||||
|
<polyline points="10 9 9 9 8 9" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<svg {...common}>
|
||||||
|
<rect x="3" y="3" width="18" height="18" rx="2" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
|
||||||
const StyledMenuItem = styled(MenuItem)(() => ({
|
function isDarkMode() {
|
||||||
gap: '8px',
|
if (typeof window === 'undefined') return false;
|
||||||
padding: '8px 16px',
|
return document.documentElement.dataset.colorMode === 'dark' ||
|
||||||
transition: 'background-color 200ms ease',
|
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
'&:hover': {
|
}
|
||||||
backgroundColor: 'var(--color-hover)',
|
|
||||||
'& .MuiListItemIcon-root': {
|
|
||||||
color: 'var(--color-selected)',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'& .MuiListItemIcon-root': {
|
|
||||||
color: 'var(--color-text)',
|
|
||||||
minWidth: '32px',
|
|
||||||
transition: 'color 200ms ease',
|
|
||||||
'& .MuiSvgIcon-root': {
|
|
||||||
fontSize: '1.25rem',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const BasePanel: React.FC<BasePanelProps> = ({
|
export const BasePanel: React.FC<BasePanelProps> = ({
|
||||||
initialPanelType = 'files',
|
initialPanelType = 'files',
|
||||||
@ -130,36 +162,30 @@ export const BasePanel: React.FC<BasePanelProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { tldrawPreferences } = useTLDraw();
|
const { tldrawPreferences } = useTLDraw();
|
||||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
const [prefersDarkMode, setPrefersDarkMode] = useState(isDarkMode());
|
||||||
const [menuAnchorEl, setMenuAnchorEl] = React.useState<null | HTMLElement>(null);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Create a dynamic theme based on TLDraw preferences
|
useEffect(() => {
|
||||||
const theme = useMemo(() => {
|
const mq = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
let mode: 'light' | 'dark';
|
const handler = () => setPrefersDarkMode(isDarkMode());
|
||||||
|
mq.addEventListener?.('change', handler);
|
||||||
|
return () => mq.removeEventListener?.('change', handler);
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (tldrawPreferences?.colorScheme === 'system') {
|
const colorMode = (tldrawPreferences?.colorScheme === 'system' ? prefersDarkMode : tldrawPreferences?.colorScheme === 'dark')
|
||||||
mode = prefersDarkMode ? 'dark' : 'light';
|
? 'dark'
|
||||||
} else {
|
: 'light';
|
||||||
mode = tldrawPreferences?.colorScheme === 'dark' ? 'dark' : 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
return createTheme({
|
|
||||||
palette: {
|
|
||||||
mode,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, [tldrawPreferences?.colorScheme, prefersDarkMode]);
|
|
||||||
|
|
||||||
const isExamMarkerRoute = location.pathname === '/exam-marker';
|
const isExamMarkerRoute = location.pathname === '/exam-marker';
|
||||||
const availablePanels = isExamMarkerRoute ? PANEL_TYPES.examMarker : PANEL_TYPES.default;
|
const availablePanels = isExamMarkerRoute ? PANEL_TYPES.examMarker : PANEL_TYPES.default;
|
||||||
|
|
||||||
const [currentPanelType, setCurrentPanelType] = React.useState<PanelType>(
|
const [currentPanelType, setCurrentPanelType] = useState<PanelType>(
|
||||||
isExamMarkerRoute ? 'exam-marker' : initialPanelType
|
isExamMarkerRoute ? 'exam-marker' : initialPanelType
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use controlled state if provided, otherwise use internal state
|
const [internalIsExpanded, setInternalIsExpanded] = useState(true);
|
||||||
const [internalIsExpanded, setInternalIsExpanded] = React.useState(true);
|
const [internalIsPinned, setInternalIsPinned] = useState(true);
|
||||||
const [internalIsPinned, setInternalIsPinned] = React.useState(true);
|
|
||||||
|
|
||||||
const isExpanded = controlledIsExpanded ?? internalIsExpanded;
|
const isExpanded = controlledIsExpanded ?? internalIsExpanded;
|
||||||
const isPinned = controlledIsPinned ?? internalIsPinned;
|
const isPinned = controlledIsPinned ?? internalIsPinned;
|
||||||
@ -178,87 +204,24 @@ export const BasePanel: React.FC<BasePanelProps> = ({
|
|||||||
const panelRef = useRef<HTMLDivElement>(null);
|
const panelRef = useRef<HTMLDivElement>(null);
|
||||||
const dimensions = PANEL_DIMENSIONS[currentPanelType as keyof typeof PANEL_DIMENSIONS];
|
const dimensions = PANEL_DIMENSIONS[currentPanelType as keyof typeof PANEL_DIMENSIONS];
|
||||||
|
|
||||||
// Handle click outside
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
// Don't close if pinned
|
|
||||||
if (isPinned) return;
|
if (isPinned) return;
|
||||||
|
|
||||||
// Check if click is outside panel
|
|
||||||
const isClickOutside = panelRef.current && !panelRef.current.contains(event.target as Node);
|
const isClickOutside = panelRef.current && !panelRef.current.contains(event.target as Node);
|
||||||
|
|
||||||
// Check if click is not on a panel-related element
|
|
||||||
const target = event.target as HTMLElement;
|
const target = event.target as HTMLElement;
|
||||||
const isPanelElement = target.closest('.panel-root, .panel-handle, .tlui-button');
|
const isPanelElement = target.closest('.panel-root, .panel-handle, .tlui-button');
|
||||||
|
|
||||||
if (isClickOutside && !isPanelElement) {
|
if (isClickOutside && !isPanelElement) {
|
||||||
handleExpandedChange(false);
|
handleExpandedChange(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isExpanded) {
|
if (isExpanded) {
|
||||||
document.addEventListener('mousedown', handleClickOutside);
|
document.addEventListener('mousedown', handleClickOutside);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('mousedown', handleClickOutside);
|
document.removeEventListener('mousedown', handleClickOutside);
|
||||||
};
|
};
|
||||||
}, [isExpanded, isPinned]);
|
}, [isExpanded, isPinned]);
|
||||||
|
|
||||||
const getIconForPanel = (panelId: PanelType) => {
|
|
||||||
switch (panelId) {
|
|
||||||
case 'cabinets':
|
|
||||||
return <NavigationIcon />;
|
|
||||||
case 'cc-shapes':
|
|
||||||
return <ShapesIcon />;
|
|
||||||
case 'transcription':
|
|
||||||
return <MicIcon />;
|
|
||||||
case 'slides':
|
|
||||||
return <SlidesIcon />;
|
|
||||||
case 'youtube':
|
|
||||||
return <YouTubeIcon />;
|
|
||||||
case 'graph':
|
|
||||||
return <GraphIcon />;
|
|
||||||
case 'search':
|
|
||||||
return <SearchIcon />;
|
|
||||||
case 'navigation':
|
|
||||||
return <NavigationIcon />;
|
|
||||||
case 'node-snapshot':
|
|
||||||
return <NodeIcon />;
|
|
||||||
case 'exam-marker':
|
|
||||||
return <ExamIcon />;
|
|
||||||
default:
|
|
||||||
return <ShapesIcon />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDescriptionForPanel = (panelId: PanelType) => {
|
|
||||||
switch (panelId) {
|
|
||||||
case 'cabinets':
|
|
||||||
return 'Manage file cabinets';
|
|
||||||
case 'transcription':
|
|
||||||
return 'Record and transcribe lessons';
|
|
||||||
case 'cc-shapes':
|
|
||||||
return 'Add shapes and elements to your canvas';
|
|
||||||
case 'slides':
|
|
||||||
return 'Manage presentation slides';
|
|
||||||
case 'youtube':
|
|
||||||
return 'Embed YouTube videos';
|
|
||||||
case 'graph':
|
|
||||||
return 'View and manage graph connections';
|
|
||||||
case 'search':
|
|
||||||
return 'Search through your content';
|
|
||||||
case 'navigation':
|
|
||||||
return 'Navigate through different contexts';
|
|
||||||
case 'node-snapshot':
|
|
||||||
return 'Manage node snapshots';
|
|
||||||
case 'exam-marker':
|
|
||||||
return 'Mark and grade exams';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderCurrentPanel = () => {
|
const renderCurrentPanel = () => {
|
||||||
if (isExamMarkerRoute && currentPanelType === 'exam-marker') {
|
if (isExamMarkerRoute && currentPanelType === 'exam-marker') {
|
||||||
return examMarkerProps ? <CCExamMarkerPanel {...examMarkerProps} /> : null;
|
return examMarkerProps ? <CCExamMarkerPanel {...examMarkerProps} /> : null;
|
||||||
@ -288,16 +251,9 @@ export const BasePanel: React.FC<BasePanelProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle menu button click
|
const toggleMenu = (open: boolean) => {
|
||||||
const handleMenuClick = (event: React.MouseEvent<HTMLElement>) => {
|
setMenuOpen(open);
|
||||||
setMenuAnchorEl(event.currentTarget);
|
onMenuOpenChange(open);
|
||||||
onMenuOpenChange(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle menu close
|
|
||||||
const handleMenuClose = () => {
|
|
||||||
setMenuAnchorEl(null);
|
|
||||||
onMenuOpenChange(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -327,55 +283,61 @@ export const BasePanel: React.FC<BasePanelProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="panel-header">
|
<div className="panel-header">
|
||||||
<ThemeProvider theme={theme}>
|
<button
|
||||||
<PanelTypeButton
|
type="button"
|
||||||
onClick={handleMenuClick}
|
className="cc-btn cc-btn--secondary cc-panel-selector"
|
||||||
endIcon={<ExpandMoreIcon />}
|
onClick={() => toggleMenu(!menuOpen)}
|
||||||
startIcon={getIconForPanel(currentPanelType)}
|
>
|
||||||
>
|
<span className="cc-btn-start-icon">
|
||||||
|
{getIconSvg(currentPanelType)}
|
||||||
|
</span>
|
||||||
|
<span className="cc-btn-label">
|
||||||
{availablePanels.find(p => p.id === currentPanelType)?.label}
|
{availablePanels.find(p => p.id === currentPanelType)?.label}
|
||||||
</PanelTypeButton>
|
</span>
|
||||||
|
<span className="cc-btn-end-icon">
|
||||||
|
<svg width="1.25rem" height="1.25rem" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<polyline points="6 9 12 15 18 9" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<Menu
|
{menuOpen && (
|
||||||
anchorEl={menuAnchorEl}
|
<div className="cc-menu panel-type-menu" role="menu">
|
||||||
open={isMenuOpen}
|
|
||||||
onClose={handleMenuClose}
|
|
||||||
PaperProps={{
|
|
||||||
elevation: 8,
|
|
||||||
sx: {
|
|
||||||
border: '1px solid var(--color-divider)',
|
|
||||||
boxShadow: 'var(--shadow-popup)',
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{[...availablePanels]
|
{[...availablePanels]
|
||||||
.sort((a, b) => a.order - b.order)
|
.sort((a, b) => a.order - b.order)
|
||||||
.map(type => (
|
.map(type => (
|
||||||
<StyledMenuItem
|
<button
|
||||||
key={type.id}
|
key={type.id}
|
||||||
onClick={() => {
|
type="button"
|
||||||
setCurrentPanelType(type.id as PanelType);
|
role="menuitem"
|
||||||
handleMenuClose();
|
className={`cc-menu-item ${type.id === currentPanelType ? 'cc-menu-item--active' : ''}`}
|
||||||
}}
|
onClick={() => {
|
||||||
selected={currentPanelType === type.id}
|
setCurrentPanelType(type.id as PanelType);
|
||||||
>
|
toggleMenu(false);
|
||||||
<ListItemIcon>
|
|
||||||
{getIconForPanel(type.id as PanelType)}
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
primary={type.label}
|
|
||||||
secondary={getDescriptionForPanel(type.id as PanelType)}
|
|
||||||
primaryTypographyProps={{
|
|
||||||
sx: { color: 'var(--color-text)' }
|
|
||||||
}}
|
}}
|
||||||
secondaryTypographyProps={{
|
>
|
||||||
sx: { color: 'var(--color-text-secondary)' }
|
<span className="cc-menu-item-icon">
|
||||||
}}
|
{getIconSvg(type.id as PanelType)}
|
||||||
/>
|
</span>
|
||||||
</StyledMenuItem>
|
<span className="cc-menu-item-text">
|
||||||
))}
|
<span className="cc-menu-item-primary">{type.label}</span>
|
||||||
</Menu>
|
<span className="cc-menu-item-secondary">
|
||||||
</ThemeProvider>
|
{type.id === 'cabinets' && 'Manage file cabinets'}
|
||||||
|
{type.id === 'transcription' && 'Record and transcribe lessons'}
|
||||||
|
{type.id === 'cc-shapes' && 'Add shapes and elements to your canvas'}
|
||||||
|
{type.id === 'slides' && 'Manage presentation slides'}
|
||||||
|
{type.id === 'youtube' && 'Embed YouTube videos'}
|
||||||
|
{type.id === 'graph' && 'View and manage graph connections'}
|
||||||
|
{type.id === 'search' && 'Search through your content'}
|
||||||
|
{type.id === 'navigation' && 'Navigate through different contexts'}
|
||||||
|
{type.id === 'node-snapshot' && 'Manage node snapshots'}
|
||||||
|
{type.id === 'exam-marker' && 'Mark and grade exams'}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="panel-header-actions">
|
<div className="panel-header-actions">
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
@ -383,16 +345,36 @@ export const BasePanel: React.FC<BasePanelProps> = ({
|
|||||||
onClick={handlePinToggle}
|
onClick={handlePinToggle}
|
||||||
className="pin-button"
|
className="pin-button"
|
||||||
>
|
>
|
||||||
{isPinned ? <PushPinIcon /> : <PushPinOutlinedIcon />}
|
<span className="cc-icon-button">
|
||||||
|
<svg
|
||||||
|
width="1.25rem"
|
||||||
|
height="1.25rem"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
{isPinned ? (
|
||||||
|
<>
|
||||||
|
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 6.91-1.01L12 2z" />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<circle cx="12" cy="12" r="10" />
|
||||||
|
<path d="M7.5 7.5l9 9" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ThemeProvider theme={theme}>
|
|
||||||
<div className="panel-content">
|
<div className="panel-content">
|
||||||
{renderCurrentPanel()}
|
{renderCurrentPanel()}
|
||||||
</div>
|
</div>
|
||||||
</ThemeProvider>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user