UNPKG

@nextcloud/vue

Version:
224 lines (223 loc) 7.36 kB
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