PaneLayout.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <template>
  2. <Splitpanes
  3. class="smart-splitter"
  4. :rtl="SIDEBAR_ON_LEFT && mdAndLarger"
  5. :class="{
  6. '!flex-row-reverse': SIDEBAR_ON_LEFT && mdAndLarger,
  7. }"
  8. :horizontal="!mdAndLarger"
  9. @resize="setPaneEvent($event, 'vertical')"
  10. >
  11. <Pane
  12. :size="PANE_MAIN_SIZE"
  13. min-size="65"
  14. class="hide-scrollbar !overflow-auto flex flex-col"
  15. >
  16. <Splitpanes
  17. class="smart-splitter"
  18. :horizontal="COLUMN_LAYOUT"
  19. @resize="setPaneEvent($event, 'horizontal')"
  20. >
  21. <Pane
  22. :size="PANE_MAIN_TOP_SIZE"
  23. class="hide-scrollbar !overflow-auto flex flex-col"
  24. >
  25. <slot name="primary" />
  26. </Pane>
  27. <Pane
  28. :size="PANE_MAIN_BOTTOM_SIZE"
  29. class="flex flex-col hide-scrollbar !overflow-auto"
  30. >
  31. <slot name="secondary" />
  32. </Pane>
  33. </Splitpanes>
  34. </Pane>
  35. <Pane
  36. v-if="SIDEBAR && hasSidebar"
  37. :size="PANE_SIDEBAR_SIZE"
  38. min-size="20"
  39. class="hide-scrollbar !overflow-auto flex flex-col"
  40. >
  41. <slot name="sidebar" />
  42. </Pane>
  43. </Splitpanes>
  44. </template>
  45. <script setup lang="ts">
  46. import { Splitpanes, Pane } from "splitpanes"
  47. import "splitpanes/dist/splitpanes.css"
  48. import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
  49. import { computed, useSlots, ref } from "@nuxtjs/composition-api"
  50. import { useSetting } from "~/newstore/settings"
  51. import { setLocalConfig, getLocalConfig } from "~/newstore/localpersistence"
  52. const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
  53. const breakpoints = useBreakpoints(breakpointsTailwind)
  54. const mdAndLarger = breakpoints.greater("md")
  55. const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
  56. const SIDEBAR = useSetting("SIDEBAR")
  57. const slots = useSlots()
  58. const hasSidebar = computed(() => !!slots.sidebar)
  59. const props = defineProps({
  60. layoutId: {
  61. type: String,
  62. default: null,
  63. },
  64. })
  65. type PaneEvent = {
  66. max: number
  67. min: number
  68. size: number
  69. }
  70. const PANE_SIDEBAR_SIZE = ref(25)
  71. const PANE_MAIN_SIZE = ref(75)
  72. const PANE_MAIN_TOP_SIZE = ref(45)
  73. const PANE_MAIN_BOTTOM_SIZE = ref(65)
  74. if (!COLUMN_LAYOUT.value) {
  75. PANE_MAIN_TOP_SIZE.value = 50
  76. PANE_MAIN_BOTTOM_SIZE.value = 50
  77. }
  78. function setPaneEvent(event: PaneEvent[], type: "vertical" | "horizontal") {
  79. if (!props.layoutId) return
  80. const storageKey = `${props.layoutId}-pane-config-${type}`
  81. setLocalConfig(storageKey, JSON.stringify(event))
  82. }
  83. function populatePaneEvent() {
  84. if (!props.layoutId) return
  85. const verticalPaneData = getPaneData("vertical")
  86. if (verticalPaneData) {
  87. const [mainPane, sidebarPane] = verticalPaneData
  88. PANE_MAIN_SIZE.value = mainPane?.size
  89. PANE_SIDEBAR_SIZE.value = sidebarPane?.size
  90. }
  91. const horizontalPaneData = getPaneData("horizontal")
  92. if (horizontalPaneData) {
  93. const [mainTopPane, mainBottomPane] = horizontalPaneData
  94. PANE_MAIN_TOP_SIZE.value = mainTopPane?.size
  95. PANE_MAIN_BOTTOM_SIZE.value = mainBottomPane?.size
  96. }
  97. }
  98. function getPaneData(type: "vertical" | "horizontal"): PaneEvent[] | null {
  99. const storageKey = `${props.layoutId}-pane-config-${type}`
  100. const paneEvent = getLocalConfig(storageKey)
  101. if (!paneEvent) return null
  102. return JSON.parse(paneEvent)
  103. }
  104. populatePaneEvent()
  105. </script>