EditorBaseLayout.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { useParams } from 'common'
  2. import { usePathname } from 'next/navigation'
  3. import { ComponentProps, ReactNode } from 'react'
  4. import { cn } from 'ui'
  5. import { ProjectLayoutWithAuth } from '../ProjectLayout'
  6. import { CollapseButton } from '../Tabs/CollapseButton'
  7. import { EditorTabs } from '../Tabs/Tabs'
  8. import { useEditorType } from './EditorsLayout.hooks'
  9. import { useTabsStateSnapshot } from '@/state/tabs'
  10. export interface ExplorerLayoutProps extends ComponentProps<typeof ProjectLayoutWithAuth> {
  11. children: ReactNode
  12. title?: string
  13. product?: string
  14. productMenuClassName?: string
  15. }
  16. export const EditorBaseLayout = ({
  17. children,
  18. title,
  19. product,
  20. productMenuClassName,
  21. productMenu,
  22. browserTitle,
  23. }: ExplorerLayoutProps) => {
  24. const { ref } = useParams()
  25. const pathname = usePathname()
  26. const editor = useEditorType()
  27. const tabs = useTabsStateSnapshot()
  28. const hasNoOpenTabs =
  29. editor === 'table' ? tabs.openTabs.filter((x) => !x.startsWith('sql')).length === 0 : false
  30. const hideTabs =
  31. pathname === `/project/${ref}/editor` || pathname === `/project/${ref}/sql` || hasNoOpenTabs
  32. const activeEditorTab = tabs.activeTab ? tabs.tabsMap[tabs.activeTab] : undefined
  33. // Prefer the live tab label so browser titles update immediately after a rename,
  34. // even when persisted tab metadata is still catching up.
  35. const activeEditorTabLabel = activeEditorTab?.label ?? activeEditorTab?.metadata?.name
  36. const activeEditorTabEntity =
  37. activeEditorTab === undefined
  38. ? undefined
  39. : editor === 'sql'
  40. ? activeEditorTab.type === 'sql'
  41. ? activeEditorTabLabel
  42. : undefined
  43. : editor === 'table'
  44. ? activeEditorTab.type !== 'sql'
  45. ? activeEditorTabLabel
  46. : undefined
  47. : undefined
  48. const mergedBrowserTitle = {
  49. ...browserTitle,
  50. section: title ?? browserTitle?.section,
  51. entity: browserTitle?.entity ?? activeEditorTabEntity,
  52. }
  53. return (
  54. <ProjectLayoutWithAuth
  55. resizableSidebar
  56. product={product}
  57. browserTitle={mergedBrowserTitle}
  58. productMenuClassName={productMenuClassName}
  59. productMenu={productMenu}
  60. >
  61. <div className="flex flex-col h-full">
  62. <div
  63. className={cn(
  64. 'h-10 md:min-h-(--header-height) flex items-center',
  65. !hideTabs ? 'bg-surface-200 dark:bg-alternative' : 'bg-surface-100'
  66. )}
  67. >
  68. {hideTabs ? <CollapseButton hideTabs={hideTabs} /> : <EditorTabs />}
  69. </div>
  70. <div className="h-full">{children}</div>
  71. </div>
  72. </ProjectLayoutWithAuth>
  73. )
  74. }