@nextcloud/vue
Version:
Nextcloud vue components
224 lines (223 loc) • 7.36 kB
JavaScript
import '../assets/NcAppSettingsDialog-DiJpVNeb.css';
import debounce from "debounce";
import Vue from "vue";
import { useIsMobile } from "../Composables/useIsMobile.mjs";
import { r as register, o as t47, a as t } from "./_l10n-BEfeU7gr.mjs";
import { N as NcDialog } from "./NcDialog-Du-BeUCp.mjs";
import NcVNodes from "../Components/NcVNodes.mjs";
import { n as normalizeComponent } from "./_plugin-vue2_normalizer-DU4iP6Vu.mjs";
register(t47);
const _sfc_main = {
name: "NcAppSettingsDialog",
components: {
NcDialog,
NcVNodes
},
provide() {
return {
registerSection: this.registerSection,
unregisterSection: this.unregisterSection
};
},
props: {
/**
* Determines the open / closed state of the modal
*/
open: {
type: Boolean,
required: true
},
/**
* Shows the navigation on desktop if true
*/
showNavigation: {
type: Boolean,
default: false
},
/**
* Selector for the popover container
*/
container: {
type: String,
default: "body"
},
/**
* Name of the settings
*/
name: {
type: String,
default: ""
},
/**
* Additional elements to add to the focus trap
*/
additionalTrapElements: {
type: Array,
default: () => []
}
},
emits: ["update:open"],
setup() {
return {
isMobile: useIsMobile()
};
},
data() {
return {
selectedSection: "",
linkClicked: false,
addedScrollListener: false,
scroller: null,
/**
* Currently registered settings sections
*
* @type {{ id: string, name: string, icon?: import('vue').VNode[] }[]}
*/
sections: []
};
},
computed: {
dialogProperties() {
return {
additionalTrapElements: this.additionalTrapElements,
closeOnClickOutside: true,
class: "app-settings",
container: this.container,
contentClasses: "app-settings__content",
size: "large",
name: this.name,
navigationClasses: "app-settings__navigation"
};
},
/**
* Check if one or more navigation entries provide icons
*/
hasNavigationIcons() {
return this.sections.some(({ icon }) => !!icon);
},
hasNavigation() {
if (this.isMobile || !this.showNavigation) {
return false;
} else {
return true;
}
},
settingsNavigationAriaLabel() {
return t("Settings navigation");
}
},
updated() {
if (!this.$refs.settingsScroller) {
return;
}
this.scroller = this.$refs.settingsScroller;
if (!this.addedScrollListener) {
this.scroller.addEventListener("scroll", this.handleScroll);
this.addedScrollListener = true;
}
},
methods: {
/**
* Called when a new section is registered
*
* @param {string} id The section ID
* @param {string} name The section name
* @param {import('vue').VNode[]|undefined} icon Optional icon component
*/
registerSection(id, name, icon) {
if (this.sections.some(({ id: otherId }) => id === otherId)) {
throw new Error(`Duplicate section id found: ${id}. Settings navigation sections must have unique section ids.`);
}
if (this.sections.some(({ name: otherName }) => name === otherName)) {
Vue.util.warn(`Duplicate section name found: ${name}. Settings navigation sections must have unique section names.`);
}
const newSections = [...this.sections, { id, name, icon }];
this.sections = newSections.sort(({ id: idA }, { id: idB }) => {
const indexOf = (id2) => this.$slots.default?.findIndex?.((vnode) => vnode?.componentOptions?.propsData?.id === id2) ?? -1;
return indexOf(idA) - indexOf(idB);
});
if (this.sections.length === 1) {
this.selectedSection = id;
}
},
/**
* Called when a section is unregistered to remove it from dialog
*
* @param {string} id The section ID
*/
unregisterSection(id) {
this.sections = this.sections.filter(({ id: otherId }) => id !== otherId);
if (this.selectedSection === id) {
this.selectedSection = this.sections[0]?.id ?? "";
}
},
/**
* Scrolls the content to the selected settings section.absolute
*
* @param {string} item the ID of the section
*/
handleSettingsNavigationClick(item) {
this.linkClicked = true;
document.getElementById("settings-section_" + item).scrollIntoView({
behavior: "smooth",
inline: "nearest"
});
this.selectedSection = item;
setTimeout(() => {
this.linkClicked = false;
}, 1e3);
},
handleCloseModal(isOpen) {
if (isOpen) {
return;
}
this.$emit("update:open", false);
this.scroller.removeEventListener("scroll", this.handleScroll);
this.addedScrollListener = false;
this.scroller.scrollTop = 0;
},
handleScroll() {
if (!this.linkClicked) {
this.unfocusNavigationItem();
}
},
// Remove selected section once the user starts scrolling
unfocusNavigationItem: debounce(function() {
this.selectedSection = "";
if (document.activeElement.className.includes("navigation-list__link")) {
document.activeElement.blur();
}
}, 300)
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _vm.open ? _c("NcDialog", _vm._b({ attrs: { "navigation-aria-label": _vm.settingsNavigationAriaLabel }, on: { "update:open": _vm.handleCloseModal }, scopedSlots: _vm._u([_vm.hasNavigation ? { key: "navigation", fn: function({ isCollapsed }) {
return [!isCollapsed ? _c("ul", { staticClass: "navigation-list" }, _vm._l(_vm.sections, function(section) {
return _c("li", { key: section.id }, [_c("a", { staticClass: "navigation-list__link", class: {
"navigation-list__link--active": section.id === _vm.selectedSection,
"navigation-list__link--icon": _vm.hasNavigationIcons
}, attrs: { "aria-current": `${section.id === _vm.selectedSection}`, "href": `#settings-section_${section.id}`, "tabindex": "0" }, on: { "click": function($event) {
$event.preventDefault();
return _vm.handleSettingsNavigationClick(section.id);
}, "keydown": function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")) return null;
return _vm.handleSettingsNavigationClick(section.id);
} } }, [_vm.hasNavigationIcons ? _c("div", { staticClass: "navigation-list__link-icon" }, [section.icon ? _c("NcVNodes", { attrs: { "vnodes": section.icon } }) : _vm._e()], 1) : _vm._e(), _c("span", { staticClass: "navigation-list__link-text" }, [_vm._v(" " + _vm._s(section.name) + " ")])])]);
}), 0) : _vm._e()];
} } : null], null, true) }, "NcDialog", _vm.dialogProperties, false), [_c("div", { ref: "settingsScroller" }, [_vm._t("default")], 2)]) : _vm._e();
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns,
false,
null,
"dd3489b8"
);
const NcAppSettingsDialog = __component__.exports;
export {
NcAppSettingsDialog as N
};
//# sourceMappingURL=NcAppSettingsDialog-DVFw09eD.mjs.map