feat: publish HoloLake model-native living system source
This commit is contained in:
parent
6ad10edde1
commit
c395dd3a99
2467 changed files with 615073 additions and 0 deletions
687
product-source/hololake-platform/src/components/Sidebar.tsx
Normal file
687
product-source/hololake-platform/src/components/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
import { useCallback, memo } from 'react'
|
||||
import type {
|
||||
FolderCreationParent, FolderNode, SidebarSelection, VaultEntry, ViewDefinition, ViewFile,
|
||||
} from '../types'
|
||||
import {
|
||||
KeyboardSensor, PointerSensor, useSensor, useSensors, type DragEndEvent,
|
||||
} from '@dnd-kit/core'
|
||||
import { sortableKeyboardCoordinates } from '@dnd-kit/sortable'
|
||||
import { FolderTree } from './FolderTree'
|
||||
import {
|
||||
computeReorder,
|
||||
useEntryCounts,
|
||||
useSidebarCollapsed,
|
||||
useSidebarSections,
|
||||
} from './sidebar/sidebarHooks'
|
||||
import {
|
||||
ContextMenuOverlay,
|
||||
CustomizeOverlay,
|
||||
FavoritesSection,
|
||||
type SidebarSectionProps,
|
||||
SidebarTitleBar,
|
||||
SidebarTopNav,
|
||||
TypesSection,
|
||||
ViewsSection,
|
||||
} from './sidebar/SidebarSections'
|
||||
import {
|
||||
SidebarCreatableLoadingSection,
|
||||
SidebarFavoritesLoadingSection,
|
||||
SidebarTypesLoadingSection,
|
||||
} from './sidebar/SidebarLoadingSections'
|
||||
import { useSidebarTypeInteractions } from './sidebar/useSidebarTypeInteractions'
|
||||
import type { AppLocale } from '../lib/i18n'
|
||||
import type { FolderFileActions } from '../hooks/useFileActions'
|
||||
import type { AllNotesFileVisibility } from '../utils/allNotesFileVisibility'
|
||||
import { isTypeSectionVisible } from '../utils/typeVisibility'
|
||||
|
||||
interface SidebarProps {
|
||||
entries: VaultEntry[]
|
||||
selection: SidebarSelection
|
||||
onSelect: (selection: SidebarSelection) => void
|
||||
onSelectNote?: (entry: VaultEntry) => void
|
||||
onCreateType?: (type: string) => void
|
||||
onCreateNewType?: () => void
|
||||
onCustomizeType?: (typeName: string, icon: string, color: string) => void
|
||||
onUpdateTypeTemplate?: (typeName: string, template: string) => void
|
||||
onReorderSections?: (orderedTypes: { typeName: string; order: number }[]) => void
|
||||
onRenameSection?: (typeName: string, label: string) => void
|
||||
onDeleteType?: (typeName: string) => void
|
||||
onToggleTypeVisibility?: (typeName: string, typeEntryPath?: string) => void
|
||||
onSelectFavorite?: (entry: VaultEntry) => void
|
||||
onReorderFavorites?: (orderedPaths: string[]) => void
|
||||
views?: ViewFile[]
|
||||
onCreateView?: () => void
|
||||
onEditView?: (filename: string, rootPath?: string) => void
|
||||
onDeleteView?: (filename: string, rootPath?: string) => void
|
||||
onUpdateViewDefinition?: (filename: string, patch: Partial<ViewDefinition>, rootPath?: string) => void
|
||||
onReorderViews?: (orderedFilenames: string[]) => void
|
||||
folders?: FolderNode[]
|
||||
onCreateFolder?: (name: string, parent?: FolderCreationParent) => Promise<boolean> | boolean
|
||||
onRenameFolder?: (folderPath: string, nextName: string) => Promise<boolean> | boolean
|
||||
onDeleteFolder?: (folderPath: string) => void
|
||||
folderFileActions?: FolderFileActions
|
||||
renamingFolderPath?: string | null
|
||||
onStartRenameFolder?: (folderPath: string) => void
|
||||
onCancelRenameFolder?: () => void
|
||||
vaultRootPath?: string
|
||||
workspaceOrder?: readonly string[]
|
||||
showInbox?: boolean
|
||||
inboxCount?: number
|
||||
allNotesFileVisibility?: AllNotesFileVisibility
|
||||
pluralizeTypeLabels?: boolean
|
||||
locale?: AppLocale
|
||||
onCollapse?: () => void
|
||||
onGoBack?: () => void
|
||||
onGoForward?: () => void
|
||||
canGoBack?: boolean
|
||||
canGoForward?: boolean
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
interface SidebarNavigationProps extends Pick<
|
||||
SidebarProps,
|
||||
| 'entries'
|
||||
| 'selection'
|
||||
| 'onSelect'
|
||||
| 'onSelectFavorite'
|
||||
| 'onReorderFavorites'
|
||||
| 'views'
|
||||
| 'onCreateView'
|
||||
| 'onEditView'
|
||||
| 'onDeleteView'
|
||||
| 'onUpdateViewDefinition'
|
||||
| 'onReorderViews'
|
||||
| 'folders'
|
||||
| 'onCreateFolder'
|
||||
| 'onRenameFolder'
|
||||
| 'onDeleteFolder'
|
||||
| 'folderFileActions'
|
||||
| 'renamingFolderPath'
|
||||
| 'onStartRenameFolder'
|
||||
| 'onCancelRenameFolder'
|
||||
| 'vaultRootPath'
|
||||
| 'workspaceOrder'
|
||||
| 'showInbox'
|
||||
| 'inboxCount'
|
||||
| 'onCreateNewType'
|
||||
| 'locale'
|
||||
| 'loading'
|
||||
> {
|
||||
activeCount: number
|
||||
archivedCount: number
|
||||
groupCollapsed: ReturnType<typeof useSidebarCollapsed>['collapsed']
|
||||
toggleGroup: ReturnType<typeof useSidebarCollapsed>['toggle']
|
||||
visibleSections: ReturnType<typeof useSidebarSections>['visibleSections']
|
||||
allSectionGroups: ReturnType<typeof useSidebarSections>['allSectionGroups']
|
||||
sectionIds: string[]
|
||||
sensors: ReturnType<typeof useSensors>
|
||||
handleDragEnd: (event: DragEndEvent) => void
|
||||
sectionProps: SidebarSectionProps
|
||||
typeInteractions: ReturnType<typeof useSidebarTypeInteractions>
|
||||
isSectionVisible: (type: string) => boolean
|
||||
toggleVisibility: (type: string, typeEntryPath?: string) => void
|
||||
}
|
||||
|
||||
type SidebarFavoritesNavigationProps = Pick<
|
||||
SidebarNavigationProps,
|
||||
| 'loading'
|
||||
| 'entries'
|
||||
| 'selection'
|
||||
| 'onSelect'
|
||||
| 'onSelectFavorite'
|
||||
| 'onReorderFavorites'
|
||||
| 'groupCollapsed'
|
||||
| 'toggleGroup'
|
||||
| 'locale'
|
||||
>
|
||||
|
||||
type SidebarViewsNavigationProps = Pick<
|
||||
SidebarNavigationProps,
|
||||
| 'loading'
|
||||
| 'views'
|
||||
| 'selection'
|
||||
| 'onSelect'
|
||||
| 'onCreateView'
|
||||
| 'onEditView'
|
||||
| 'onDeleteView'
|
||||
| 'onUpdateViewDefinition'
|
||||
| 'onReorderViews'
|
||||
| 'groupCollapsed'
|
||||
| 'toggleGroup'
|
||||
| 'sensors'
|
||||
| 'entries'
|
||||
| 'locale'
|
||||
>
|
||||
|
||||
type SidebarTypesNavigationProps = Pick<
|
||||
SidebarNavigationProps,
|
||||
| 'loading'
|
||||
| 'entries'
|
||||
| 'visibleSections'
|
||||
| 'allSectionGroups'
|
||||
| 'sectionIds'
|
||||
| 'sensors'
|
||||
| 'handleDragEnd'
|
||||
| 'sectionProps'
|
||||
| 'groupCollapsed'
|
||||
| 'toggleGroup'
|
||||
| 'typeInteractions'
|
||||
| 'isSectionVisible'
|
||||
| 'toggleVisibility'
|
||||
| 'onCreateNewType'
|
||||
| 'workspaceOrder'
|
||||
| 'locale'
|
||||
>
|
||||
|
||||
type SidebarFoldersNavigationProps = Pick<
|
||||
SidebarNavigationProps,
|
||||
| 'loading'
|
||||
| 'folders'
|
||||
| 'selection'
|
||||
| 'onSelect'
|
||||
| 'onCreateFolder'
|
||||
| 'onRenameFolder'
|
||||
| 'onDeleteFolder'
|
||||
| 'folderFileActions'
|
||||
| 'renamingFolderPath'
|
||||
| 'onStartRenameFolder'
|
||||
| 'onCancelRenameFolder'
|
||||
| 'vaultRootPath'
|
||||
| 'groupCollapsed'
|
||||
| 'toggleGroup'
|
||||
| 'locale'
|
||||
>
|
||||
|
||||
function SidebarFavoritesNavigation({
|
||||
loading,
|
||||
entries,
|
||||
selection,
|
||||
onSelect,
|
||||
onSelectFavorite,
|
||||
onReorderFavorites,
|
||||
groupCollapsed,
|
||||
toggleGroup,
|
||||
locale,
|
||||
}: SidebarFavoritesNavigationProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<SidebarFavoritesLoadingSection
|
||||
collapsed={groupCollapsed.favorites}
|
||||
locale={locale}
|
||||
onToggle={() => toggleGroup('favorites')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border-b border-border">
|
||||
<FavoritesSection
|
||||
entries={entries}
|
||||
selection={selection}
|
||||
onSelect={onSelect}
|
||||
onSelectNote={onSelectFavorite}
|
||||
onReorder={onReorderFavorites}
|
||||
collapsed={groupCollapsed.favorites}
|
||||
locale={locale}
|
||||
onToggle={() => toggleGroup('favorites')}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarViewsNavigation({
|
||||
loading,
|
||||
views,
|
||||
selection,
|
||||
onSelect,
|
||||
onCreateView,
|
||||
onEditView,
|
||||
onDeleteView,
|
||||
onUpdateViewDefinition,
|
||||
onReorderViews,
|
||||
groupCollapsed,
|
||||
toggleGroup,
|
||||
sensors,
|
||||
entries,
|
||||
locale,
|
||||
}: SidebarViewsNavigationProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<SidebarCreatableLoadingSection
|
||||
collapsed={groupCollapsed.views}
|
||||
kind="views"
|
||||
locale={locale}
|
||||
onCreate={onCreateView}
|
||||
onToggle={() => toggleGroup('views')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ViewsSection
|
||||
views={views ?? []}
|
||||
selection={selection}
|
||||
onSelect={onSelect}
|
||||
collapsed={groupCollapsed.views}
|
||||
onToggle={() => toggleGroup('views')}
|
||||
onCreateView={onCreateView}
|
||||
onEditView={onEditView}
|
||||
onDeleteView={onDeleteView}
|
||||
onUpdateViewDefinition={onUpdateViewDefinition}
|
||||
onReorderViews={onReorderViews}
|
||||
sensors={sensors}
|
||||
entries={entries}
|
||||
locale={locale}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarTypesNavigation({
|
||||
loading,
|
||||
visibleSections,
|
||||
allSectionGroups,
|
||||
sectionIds,
|
||||
sensors,
|
||||
handleDragEnd,
|
||||
sectionProps,
|
||||
groupCollapsed,
|
||||
toggleGroup,
|
||||
typeInteractions,
|
||||
isSectionVisible,
|
||||
toggleVisibility,
|
||||
onCreateNewType,
|
||||
workspaceOrder,
|
||||
locale,
|
||||
}: SidebarTypesNavigationProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<SidebarTypesLoadingSection
|
||||
collapsed={groupCollapsed.sections}
|
||||
locale={locale}
|
||||
onCreateNewType={onCreateNewType}
|
||||
onToggle={() => toggleGroup('sections')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<TypesSection
|
||||
entries={sectionProps.entries}
|
||||
visibleSections={visibleSections}
|
||||
allSectionGroups={allSectionGroups}
|
||||
sectionIds={sectionIds}
|
||||
sensors={sensors}
|
||||
handleDragEnd={handleDragEnd}
|
||||
sectionProps={sectionProps}
|
||||
collapsed={groupCollapsed.sections}
|
||||
onToggle={() => toggleGroup('sections')}
|
||||
showCustomize={typeInteractions.showCustomize}
|
||||
setShowCustomize={typeInteractions.setShowCustomize}
|
||||
isSectionVisible={isSectionVisible}
|
||||
toggleVisibility={toggleVisibility}
|
||||
onCreateNewType={onCreateNewType}
|
||||
customizeRef={typeInteractions.customizeRef}
|
||||
workspaceOrder={workspaceOrder}
|
||||
locale={locale}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarFoldersNavigation({
|
||||
loading,
|
||||
folders,
|
||||
selection,
|
||||
onSelect,
|
||||
onCreateFolder,
|
||||
onRenameFolder,
|
||||
onDeleteFolder,
|
||||
folderFileActions,
|
||||
renamingFolderPath,
|
||||
onStartRenameFolder,
|
||||
onCancelRenameFolder,
|
||||
vaultRootPath,
|
||||
groupCollapsed,
|
||||
toggleGroup,
|
||||
locale,
|
||||
}: SidebarFoldersNavigationProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<SidebarCreatableLoadingSection
|
||||
collapsed={groupCollapsed.folders}
|
||||
kind="folders"
|
||||
locale={locale}
|
||||
onToggle={() => toggleGroup('folders')}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<FolderTree
|
||||
folders={folders ?? []}
|
||||
selection={selection}
|
||||
onSelect={onSelect}
|
||||
onCreateFolder={onCreateFolder}
|
||||
onRenameFolder={onRenameFolder}
|
||||
onDeleteFolder={onDeleteFolder}
|
||||
folderFileActions={folderFileActions}
|
||||
renamingFolderPath={renamingFolderPath}
|
||||
onStartRenameFolder={onStartRenameFolder}
|
||||
onCancelRenameFolder={onCancelRenameFolder}
|
||||
collapsed={groupCollapsed.folders}
|
||||
locale={locale}
|
||||
onToggle={() => toggleGroup('folders')}
|
||||
vaultRootPath={vaultRootPath}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarTopNavigation(props: SidebarNavigationProps) {
|
||||
return (
|
||||
<>
|
||||
<SidebarTopNav
|
||||
selection={props.selection}
|
||||
onSelect={props.onSelect}
|
||||
showInbox={props.showInbox ?? true}
|
||||
inboxCount={props.inboxCount ?? 0}
|
||||
activeCount={props.activeCount}
|
||||
archivedCount={props.archivedCount}
|
||||
locale={props.locale ?? 'en'}
|
||||
loading={props.loading ?? false}
|
||||
/>
|
||||
{(props.loading || props.entries.some((entry) => entry.favorite && !entry.archived)) && (
|
||||
<SidebarFavoritesNavigation
|
||||
loading={props.loading}
|
||||
entries={props.entries}
|
||||
selection={props.selection}
|
||||
onSelect={props.onSelect}
|
||||
onSelectFavorite={props.onSelectFavorite}
|
||||
onReorderFavorites={props.onReorderFavorites}
|
||||
groupCollapsed={props.groupCollapsed}
|
||||
toggleGroup={props.toggleGroup}
|
||||
locale={props.locale}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarViewAndTypeNavigation(props: SidebarNavigationProps) {
|
||||
const views = props.views ?? []
|
||||
const hasViews = props.loading || views.length > 0 || !!props.onCreateView
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasViews && (
|
||||
<SidebarViewsNavigation
|
||||
loading={props.loading}
|
||||
views={views}
|
||||
selection={props.selection}
|
||||
onSelect={props.onSelect}
|
||||
onCreateView={props.onCreateView}
|
||||
onEditView={props.onEditView}
|
||||
onDeleteView={props.onDeleteView}
|
||||
onUpdateViewDefinition={props.onUpdateViewDefinition}
|
||||
onReorderViews={props.onReorderViews}
|
||||
groupCollapsed={props.groupCollapsed}
|
||||
toggleGroup={props.toggleGroup}
|
||||
sensors={props.sensors}
|
||||
entries={props.entries}
|
||||
locale={props.locale}
|
||||
/>
|
||||
)}
|
||||
<SidebarTypesNavigation
|
||||
loading={props.loading}
|
||||
entries={props.entries}
|
||||
visibleSections={props.visibleSections}
|
||||
allSectionGroups={props.allSectionGroups}
|
||||
sectionIds={props.sectionIds}
|
||||
sensors={props.sensors}
|
||||
handleDragEnd={props.handleDragEnd}
|
||||
sectionProps={props.sectionProps}
|
||||
groupCollapsed={props.groupCollapsed}
|
||||
toggleGroup={props.toggleGroup}
|
||||
typeInteractions={props.typeInteractions}
|
||||
isSectionVisible={props.isSectionVisible}
|
||||
toggleVisibility={props.toggleVisibility}
|
||||
onCreateNewType={props.onCreateNewType}
|
||||
workspaceOrder={props.workspaceOrder}
|
||||
locale={props.locale}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarNavigation(props: SidebarNavigationProps) {
|
||||
return (
|
||||
<nav className="flex-1 overflow-y-auto">
|
||||
<SidebarTopNavigation {...props} />
|
||||
<SidebarViewAndTypeNavigation {...props} />
|
||||
<SidebarFoldersNavigation
|
||||
loading={props.loading}
|
||||
folders={props.folders ?? []}
|
||||
selection={props.selection}
|
||||
onSelect={props.onSelect}
|
||||
onCreateFolder={props.onCreateFolder}
|
||||
onRenameFolder={props.onRenameFolder}
|
||||
onDeleteFolder={props.onDeleteFolder}
|
||||
folderFileActions={props.folderFileActions}
|
||||
renamingFolderPath={props.renamingFolderPath}
|
||||
onStartRenameFolder={props.onStartRenameFolder}
|
||||
onCancelRenameFolder={props.onCancelRenameFolder}
|
||||
vaultRootPath={props.vaultRootPath}
|
||||
groupCollapsed={props.groupCollapsed}
|
||||
toggleGroup={props.toggleGroup}
|
||||
locale={props.locale}
|
||||
/>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
function useSidebarDndSensors() {
|
||||
return useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
|
||||
)
|
||||
}
|
||||
|
||||
function invokeTypeVisibilityToggle(
|
||||
onToggleTypeVisibility: SidebarProps['onToggleTypeVisibility'],
|
||||
type: string,
|
||||
typeEntryPath?: string,
|
||||
) {
|
||||
if (typeEntryPath) {
|
||||
onToggleTypeVisibility?.(type, typeEntryPath)
|
||||
return
|
||||
}
|
||||
onToggleTypeVisibility?.(type)
|
||||
}
|
||||
|
||||
function useSidebarRuntime({
|
||||
entries,
|
||||
selection,
|
||||
onSelect,
|
||||
onSelectNote,
|
||||
onCustomizeType,
|
||||
onUpdateTypeTemplate,
|
||||
onReorderSections,
|
||||
onRenameSection,
|
||||
onDeleteType,
|
||||
onToggleTypeVisibility,
|
||||
allNotesFileVisibility,
|
||||
pluralizeTypeLabels = true,
|
||||
locale = 'en',
|
||||
}: SidebarProps) {
|
||||
const {
|
||||
typeEntryMap,
|
||||
typeVisibility,
|
||||
allSectionGroups,
|
||||
visibleSections,
|
||||
sectionIds,
|
||||
} = useSidebarSections(entries, pluralizeTypeLabels)
|
||||
const { activeCount, archivedCount } = useEntryCounts(entries, allNotesFileVisibility)
|
||||
const { collapsed: groupCollapsed, toggle: toggleGroup } = useSidebarCollapsed()
|
||||
const typeInteractions = useSidebarTypeInteractions({
|
||||
allSectionGroups,
|
||||
typeEntryMap,
|
||||
onCustomizeType,
|
||||
onUpdateTypeTemplate,
|
||||
onRenameSection,
|
||||
onDeleteType,
|
||||
})
|
||||
|
||||
const isSectionVisible = useCallback((type: string) => (
|
||||
isTypeSectionVisible(entries, type, typeVisibility)
|
||||
), [entries, typeVisibility])
|
||||
const toggleVisibility = useCallback((type: string, typeEntryPath?: string) => {
|
||||
invokeTypeVisibilityToggle(onToggleTypeVisibility, type, typeEntryPath)
|
||||
}, [onToggleTypeVisibility])
|
||||
const selectTypeNote = useCallback((type: string) => {
|
||||
const typeEntry = (Reflect.get(typeEntryMap, type) as VaultEntry | undefined)
|
||||
?? (Reflect.get(typeEntryMap, type.toLowerCase()) as VaultEntry | undefined)
|
||||
if (typeEntry) onSelectNote?.(typeEntry)
|
||||
}, [onSelectNote, typeEntryMap])
|
||||
|
||||
const sensors = useSidebarDndSensors()
|
||||
|
||||
const handleDragEnd = useCallback((event: DragEndEvent) => {
|
||||
const { active, over } = event
|
||||
if (!over || active.id === over.id) return
|
||||
const reordered = computeReorder(sectionIds, active.id as string, over.id as string)
|
||||
if (reordered) onReorderSections?.(reordered.map((typeName, order) => ({ typeName, order })))
|
||||
}, [sectionIds, onReorderSections])
|
||||
|
||||
const sectionProps: SidebarSectionProps = {
|
||||
entries,
|
||||
selection,
|
||||
locale,
|
||||
onSelect,
|
||||
onContextMenu: typeInteractions.handleContextMenu,
|
||||
renamingType: typeInteractions.renamingType,
|
||||
renameInitialValue: typeInteractions.renameInitialValue,
|
||||
onRenameSubmit: typeInteractions.handleRenameSubmit,
|
||||
onRenameCancel: typeInteractions.cancelRename,
|
||||
onStartRename: typeInteractions.handleStartRename,
|
||||
onSelectTypeNote: selectTypeNote,
|
||||
}
|
||||
|
||||
return {
|
||||
activeCount,
|
||||
allSectionGroups,
|
||||
archivedCount,
|
||||
groupCollapsed,
|
||||
handleDragEnd,
|
||||
isSectionVisible,
|
||||
sectionIds,
|
||||
sectionProps,
|
||||
sensors,
|
||||
toggleGroup,
|
||||
toggleVisibility,
|
||||
typeEntryMap,
|
||||
typeVisibility,
|
||||
typeInteractions,
|
||||
visibleSections,
|
||||
}
|
||||
}
|
||||
|
||||
function SidebarRuntimeNavigation({
|
||||
props,
|
||||
runtime,
|
||||
}: {
|
||||
props: SidebarProps
|
||||
runtime: ReturnType<typeof useSidebarRuntime>
|
||||
}) {
|
||||
return (
|
||||
<SidebarNavigation
|
||||
entries={props.entries}
|
||||
selection={props.selection}
|
||||
onSelect={props.onSelect}
|
||||
onSelectFavorite={props.onSelectFavorite}
|
||||
onReorderFavorites={props.onReorderFavorites}
|
||||
views={props.views}
|
||||
onCreateView={props.onCreateView}
|
||||
onEditView={props.onEditView}
|
||||
onDeleteView={props.onDeleteView}
|
||||
onUpdateViewDefinition={props.onUpdateViewDefinition}
|
||||
onReorderViews={props.onReorderViews}
|
||||
folders={props.folders}
|
||||
onCreateFolder={props.onCreateFolder}
|
||||
onRenameFolder={props.onRenameFolder}
|
||||
onDeleteFolder={props.onDeleteFolder}
|
||||
folderFileActions={props.folderFileActions}
|
||||
renamingFolderPath={props.renamingFolderPath}
|
||||
onStartRenameFolder={props.onStartRenameFolder}
|
||||
onCancelRenameFolder={props.onCancelRenameFolder}
|
||||
vaultRootPath={props.vaultRootPath}
|
||||
workspaceOrder={props.workspaceOrder}
|
||||
showInbox={props.showInbox}
|
||||
inboxCount={props.inboxCount}
|
||||
locale={props.locale}
|
||||
loading={props.loading}
|
||||
onCreateNewType={props.onCreateNewType}
|
||||
activeCount={runtime.activeCount}
|
||||
archivedCount={runtime.archivedCount}
|
||||
groupCollapsed={runtime.groupCollapsed}
|
||||
toggleGroup={runtime.toggleGroup}
|
||||
visibleSections={runtime.visibleSections}
|
||||
allSectionGroups={runtime.allSectionGroups}
|
||||
sectionIds={runtime.sectionIds}
|
||||
sensors={runtime.sensors}
|
||||
handleDragEnd={runtime.handleDragEnd}
|
||||
sectionProps={runtime.sectionProps}
|
||||
typeInteractions={runtime.typeInteractions}
|
||||
isSectionVisible={runtime.isSectionVisible}
|
||||
toggleVisibility={runtime.toggleVisibility}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarInteractionOverlays({
|
||||
locale,
|
||||
runtime,
|
||||
}: {
|
||||
locale: AppLocale
|
||||
runtime: ReturnType<typeof useSidebarRuntime>
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<ContextMenuOverlay
|
||||
pos={runtime.typeInteractions.contextMenuPos}
|
||||
type={runtime.typeInteractions.contextMenuType}
|
||||
innerRef={runtime.typeInteractions.contextMenuRef}
|
||||
onOpenCustomize={runtime.typeInteractions.openCustomizeTarget}
|
||||
onStartRename={runtime.typeInteractions.handleStartRename}
|
||||
onDelete={runtime.typeInteractions.handleDeleteType}
|
||||
locale={locale}
|
||||
/>
|
||||
<CustomizeOverlay
|
||||
target={runtime.typeInteractions.customizeTarget}
|
||||
typeEntryMap={runtime.typeEntryMap}
|
||||
innerRef={runtime.typeInteractions.popoverRef}
|
||||
onCustomize={runtime.typeInteractions.handleCustomize}
|
||||
onChangeTemplate={runtime.typeInteractions.handleChangeTemplate}
|
||||
onClose={runtime.typeInteractions.closeCustomizeTarget}
|
||||
locale={locale}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const Sidebar = memo(function Sidebar(props: SidebarProps) {
|
||||
const locale = props.locale ?? 'en'
|
||||
const runtime = useSidebarRuntime(props)
|
||||
|
||||
return (
|
||||
<aside className="flex h-full flex-col overflow-hidden border-r border-[var(--sidebar-border)] bg-sidebar text-sidebar-foreground">
|
||||
<SidebarTitleBar
|
||||
locale={locale}
|
||||
onCollapse={props.onCollapse}
|
||||
onGoBack={props.onGoBack}
|
||||
onGoForward={props.onGoForward}
|
||||
canGoBack={props.canGoBack}
|
||||
canGoForward={props.canGoForward}
|
||||
/>
|
||||
<SidebarRuntimeNavigation props={props} runtime={runtime} />
|
||||
<SidebarInteractionOverlays locale={locale} runtime={runtime} />
|
||||
</aside>
|
||||
)
|
||||
})
|
||||
Loading…
Reference in a new issue