UNPKG

@nextcloud/vue

Version:
315 lines (314 loc) 10.9 kB
import '../assets/NcAppContent-BO0ksFwD.css'; import NcButton from "../Components/NcButton.mjs"; import { r as register, D as t25, a as t } from "./_l10n-DDKxBWQL.mjs"; import "../Directives/Tooltip.mjs"; import { emit } from "@nextcloud/event-bus"; import { A as ArrowRight } from "./ArrowRight-CY2b9hgN.mjs"; import { A as ArrowLeft } from "./ArrowLeft-DuT2LZOm.mjs"; import { useIsMobile } from "../Composables/useIsMobile.mjs"; import { isRTL } from "@nextcloud/l10n"; import { n as normalizeComponent } from "./_plugin-vue2_normalizer-DU4iP6Vu.mjs"; import { VTooltip } from "floating-vue"; import { getBuilder } from "@nextcloud/browser-storage"; import { useSwipe } from "@vueuse/core"; import { Pane, Splitpanes } from "splitpanes"; import "splitpanes/dist/splitpanes.css"; register(t25); const _sfc_main$1 = { name: "NcAppDetailsToggle", directives: { tooltip: VTooltip }, components: { NcButton, ArrowRight, ArrowLeft }, setup() { return { isRTL: isRTL(), isMobile: useIsMobile() }; }, computed: { title() { return t("Go back to the list"); } }, watch: { isMobile: { immediate: true, handler() { this.toggleAppNavigationButton(this.isMobile); } } }, beforeDestroy() { if (this.isMobile) { this.toggleAppNavigationButton(false); } }, methods: { toggleAppNavigationButton(hide = true) { const appNavigationToggle = document.querySelector(".app-navigation .app-navigation-toggle"); if (appNavigationToggle) { appNavigationToggle.style.display = hide ? "none" : null; if (hide === true) { emit("toggle-navigation", { open: false }); } } } } }; var _sfc_render$1 = function render() { var _vm = this, _c = _vm._self._c; return _c("NcButton", { directives: [{ name: "tooltip", rawName: "v-tooltip", value: _vm.title, expression: "title" }], staticClass: "app-details-toggle", class: { "app-details-toggle--mobile": _vm.isMobile }, attrs: { "type": "tertiary", "aria-label": _vm.title }, scopedSlots: _vm._u([{ key: "icon", fn: function() { return [_vm.isRTL ? _c("ArrowLeft", { attrs: { "size": 20 } }) : _c("ArrowRight", { attrs: { "size": 20 } })]; }, proxy: true }]) }); }; var _sfc_staticRenderFns$1 = []; var __component__$1 = /* @__PURE__ */ normalizeComponent( _sfc_main$1, _sfc_render$1, _sfc_staticRenderFns$1, false, null, "089eb524" ); const NcAppDetailsToggle = __component__$1.exports; const browserStorage = getBuilder("nextcloud").persist().build(); const _sfc_main = { name: "NcAppContent", components: { NcAppDetailsToggle, Pane, Splitpanes }, props: { /** * Allows to disable the control by swipe of the app navigation open state * @deprecated will be removed with the next version - use `disableSwipe` instead */ allowSwipeNavigation: { type: Boolean, default: true }, /** * Allows to disable the control by swipe of the app navigation open state. */ disableSwipe: { type: Boolean, default: false }, /** * Allows you to set the default width of the resizable list in % on vertical-split * Allows you to set the default height of the resizable list in % on horizontal-split * Must be between listMinWidth and listMaxWidth */ listSize: { type: Number, default: 20 }, /** * Allows you to set the minimum width of the list column in % on vertical-split * Allows you to set the minimum height of the list column in % on horizontal-split */ listMinWidth: { type: Number, default: 15 }, /** * Allows you to set the maximum width of the list column in % on vertical-split * Allows you to set the maximum height of the list column in % on horizontal-split */ listMaxWidth: { type: Number, default: 40 }, /** * Specify the config key for the pane config sizes * Default is the global var appName if you use the webpack-vue-config */ paneConfigKey: { type: String, default: "" }, /** * When in mobile view, only the list or the details are shown. * * If you provide a list, you need to provide a variable * that will be set to true by the user when an element of * the list gets selected. The details will then show a back * arrow to return to the list that will update this prop to false. */ showDetails: { type: Boolean, default: true }, /** * Specify the `<h1>` page heading */ pageHeading: { type: String, default: null }, /** * Content layout used when there is a list together with content: * - `vertical-split` - a 2-column layout with list and default content separated vertically * - `no-split` - a single column layout; List is shown when `showDetails` is `false`, otherwise the default slot content is shown with a back button to return to the list. * - 'horizontal-split' - a 2-column layout with list and default content separated horizontally * On mobile screen `no-split` layout is forced. */ layout: { type: String, default: "vertical-split", validator(value) { return ["no-split", "vertical-split", "horizontal-split"].includes(value); } } }, emits: [ "update:showDetails", "resize:list" ], setup() { return { isMobile: useIsMobile(), isRTL: isRTL() }; }, data() { return { contentHeight: 0, hasList: false, hasContent: false, swiping: {}, listPaneSize: this.restorePaneConfig() }; }, computed: { paneConfigID() { if (this.paneConfigKey !== "") { return `pane-list-size-${this.paneConfigKey}`; } try { return `pane-list-size-${appName}`; } catch (e) { console.info("[INFO] AppContent:", "falling back to global nextcloud pane config"); return "pane-list-size-nextcloud"; } }, detailsPaneSize() { if (this.listPaneSize) { return 100 - this.listPaneSize; } return this.paneDefaults.details.size; }, paneDefaults() { return { list: { size: this.listSize, min: this.listMinWidth, max: this.listMaxWidth }, // set the inverse values of the details column // based on the provided (or default) values of the list column details: { size: 100 - this.listSize, min: 100 - this.listMaxWidth, max: 100 - this.listMinWidth } }; } }, updated() { this.checkSlots(); }, mounted() { if (this.allowSwipeNavigation && !this.disableSwipe) { this.swiping = useSwipe(this.$el, { onSwipeEnd: this.handleSwipe }); } this.checkSlots(); this.restorePaneConfig(); }, methods: { /** * handle the swipe event * * @param {TouchEvent} e The touch event * @param {import('@vueuse/core').SwipeDirection} direction The swipe direction of the event */ handleSwipe(e, direction) { const minSwipeX = 70; const touchZone = 300; if (Math.abs(this.swiping.lengthX) > minSwipeX) { if (this.swiping.coordsStart.x < touchZone / 2 && direction === "right") { emit("toggle-navigation", { open: true }); } else if (this.swiping.coordsStart.x < touchZone * 1.5 && direction === "left") { emit("toggle-navigation", { open: false }); } } }, handlePaneResize(event) { const listPaneSize = parseInt(event[0].size, 10); browserStorage.setItem(this.paneConfigID, JSON.stringify(listPaneSize)); this.listPaneSize = listPaneSize; this.$emit("resize:list", { size: listPaneSize }); console.debug("AppContent pane config", listPaneSize); }, // $slots is not reactive, we need to update this manually checkSlots() { this.hasList = !!this.$scopedSlots.list; this.hasContent = !!this.$scopedSlots.default; }, // browserStorage is not reactive, we need to update this manually restorePaneConfig() { const listPaneSize = parseInt(browserStorage.getItem(this.paneConfigID), 10); if (!isNaN(listPaneSize) && listPaneSize !== this.listPaneSize) { console.debug("AppContent pane config", listPaneSize); this.listPaneSize = listPaneSize; return listPaneSize; } }, /** * The user clicked the back arrow from the details view */ hideDetails() { this.$emit("update:showDetails", false); } } }; var _sfc_render = function render2() { var _vm = this, _c = _vm._self._c; return _c("main", { staticClass: "app-content no-snapper", class: { "app-content--has-list": _vm.hasList }, attrs: { "id": "app-content-vue" } }, [_vm.pageHeading ? _c("h1", { staticClass: "hidden-visually" }, [_vm._v(" " + _vm._s(_vm.pageHeading) + " ")]) : _vm._e(), _vm.hasList ? [_vm.isMobile || _vm.layout === "no-split" ? _c("div", { staticClass: "app-content-wrapper app-content-wrapper--no-split", class: { "app-content-wrapper--show-details": _vm.showDetails, "app-content-wrapper--show-list": !_vm.showDetails, "app-content-wrapper--mobile": _vm.isMobile } }, [_vm.showDetails ? _c("NcAppDetailsToggle", { nativeOn: { "click": function($event) { $event.stopPropagation(); $event.preventDefault(); return _vm.hideDetails.apply(null, arguments); } } }) : _vm._e(), !_vm.showDetails ? _vm._t("list") : _vm._t("default")], 2) : _vm.layout === "vertical-split" || _vm.layout === "horizontal-split" ? _c("div", { staticClass: "app-content-wrapper" }, [_c("Splitpanes", { staticClass: "default-theme", class: { "splitpanes--horizontal": _vm.layout === "horizontal-split", "splitpanes--vertical": _vm.layout === "vertical-split" }, attrs: { "horizontal": _vm.layout === "horizontal-split", "rtl": _vm.isRTL }, on: { "resized": _vm.handlePaneResize } }, [_c("Pane", { staticClass: "splitpanes__pane-list", attrs: { "size": _vm.listPaneSize || _vm.paneDefaults.list.size, "min-size": _vm.paneDefaults.list.min, "max-size": _vm.paneDefaults.list.max } }, [_vm._t("list")], 2), _c("Pane", { staticClass: "splitpanes__pane-details", attrs: { "size": _vm.detailsPaneSize, "min-size": _vm.paneDefaults.details.min, "max-size": _vm.paneDefaults.details.max } }, [_vm._t("default")], 2)], 1)], 1) : _vm._e()] : _vm._e(), !_vm.hasList ? _vm._t("default") : _vm._e()], 2); }; var _sfc_staticRenderFns = []; var __component__ = /* @__PURE__ */ normalizeComponent( _sfc_main, _sfc_render, _sfc_staticRenderFns, false, null, "79779e34" ); const NcAppContent = __component__.exports; export { NcAppContent as N };