UNPKG

@nextcloud/vue

Version:
1,047 lines (1,046 loc) 36.7 kB
import '../assets/NcAppSidebar-krHtMwId.css'; import { vOnClickOutside } from "@vueuse/components"; import { createFocusTrap } from "focus-trap"; import { createElementBlock, openBlock, mergeProps, createElementVNode, createCommentVNode, toDisplayString, defineComponent, mergeModels, useModel, normalizeClass, createVNode, withCtx, resolveComponent, withKeys, withModifiers, Fragment, renderList, createBlock, renderSlot, resolveDirective, Transition, withDirectives, Teleport, normalizeStyle, vShow, createTextVNode, warn, ref, provide } from "vue"; import { I as IconArrowRight } from "./ArrowRight-DRKHUZMH.mjs"; import { I as IconClose } from "./Close-D6ngJ4t9.mjs"; import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.mjs"; import { getCanonicalLocale } from "@nextcloud/l10n"; import { _ as _sfc_main$6 } from "./NcVNodes.vue_vue_type_script_lang-BqUHinRZ.mjs"; import { useIsSmallMobile } from "../composables/useIsMobile/index.mjs"; import directive from "../directives/Focus/index.mjs"; import { r as register, C as t15, a as t } from "./_l10n-DrTiip5c.mjs"; import { c as createElementId } from "./createElementId-DhjFt1I9.mjs"; import { g as getTrapStack } from "./focusTrap-HJQ4pqHV.mjs"; import { i as isSlotPopulated, N as NcActions } from "./NcActions-DWmvh7-Y.mjs"; import { l as logger } from "./logger-D3RVzcfQ.mjs"; import { _ as _sfc_main$7 } from "./NcAppSidebarHeader.vue_vue_type_script_setup_true_lang-0j0aFDeK.mjs"; import { N as NcButton } from "./NcButton-Dc8V4Urj.mjs"; import { C as CONTENT_SELECTOR_KEY } from "./constants-DrSznhwy.mjs"; import { N as NcEmptyContent } from "./NcEmptyContent-B8-90BSI.mjs"; import { N as NcLoadingIcon } from "./NcLoadingIcon-b_ajZ_nQ.mjs"; const _sfc_main$5 = { name: "DockRightIcon", emits: ["click"], props: { title: { type: String }, fillColor: { type: String, default: "currentColor" }, size: { type: Number, default: 24 } } }; const _hoisted_1$5 = ["aria-hidden", "aria-label"]; const _hoisted_2$3 = ["fill", "width", "height"]; const _hoisted_3$3 = { d: "M20 4H4A2 2 0 0 0 2 6V18A2 2 0 0 0 4 20H20A2 2 0 0 0 22 18V6A2 2 0 0 0 20 4M15 18H4V6H15Z" }; const _hoisted_4$3 = { key: 0 }; function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, { "aria-hidden": $props.title ? null : "true", "aria-label": $props.title, class: "material-design-icon dock-right-icon", role: "img", onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event)) }), [ (openBlock(), createElementBlock("svg", { fill: $props.fillColor, class: "material-design-icon__svg", width: $props.size, height: $props.size, viewBox: "0 0 24 24" }, [ createElementVNode("path", _hoisted_3$3, [ $props.title ? (openBlock(), createElementBlock("title", _hoisted_4$3, toDisplayString($props.title), 1)) : createCommentVNode("", true) ]) ], 8, _hoisted_2$3)) ], 16, _hoisted_1$5); } const IconDockRight = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4]]); const _sfc_main$4 = { name: "StarIcon", emits: ["click"], props: { title: { type: String }, fillColor: { type: String, default: "currentColor" }, size: { type: Number, default: 24 } } }; const _hoisted_1$4 = ["aria-hidden", "aria-label"]; const _hoisted_2$2 = ["fill", "width", "height"]; const _hoisted_3$2 = { d: "M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z" }; const _hoisted_4$2 = { key: 0 }; function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, { "aria-hidden": $props.title ? null : "true", "aria-label": $props.title, class: "material-design-icon star-icon", role: "img", onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event)) }), [ (openBlock(), createElementBlock("svg", { fill: $props.fillColor, class: "material-design-icon__svg", width: $props.size, height: $props.size, viewBox: "0 0 24 24" }, [ createElementVNode("path", _hoisted_3$2, [ $props.title ? (openBlock(), createElementBlock("title", _hoisted_4$2, toDisplayString($props.title), 1)) : createCommentVNode("", true) ]) ], 8, _hoisted_2$2)) ], 16, _hoisted_1$4); } const IconStar = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3]]); const _sfc_main$3 = { name: "StarOutlineIcon", emits: ["click"], props: { title: { type: String }, fillColor: { type: String, default: "currentColor" }, size: { type: Number, default: 24 } } }; const _hoisted_1$3 = ["aria-hidden", "aria-label"]; const _hoisted_2$1 = ["fill", "width", "height"]; const _hoisted_3$1 = { d: "M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z" }; const _hoisted_4$1 = { key: 0 }; function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, { "aria-hidden": $props.title ? null : "true", "aria-label": $props.title, class: "material-design-icon star-outline-icon", role: "img", onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event)) }), [ (openBlock(), createElementBlock("svg", { fill: $props.fillColor, class: "material-design-icon__svg", width: $props.size, height: $props.size, viewBox: "0 0 24 24" }, [ createElementVNode("path", _hoisted_3$1, [ $props.title ? (openBlock(), createElementBlock("title", _hoisted_4$1, toDisplayString($props.title), 1)) : createCommentVNode("", true) ]) ], 8, _hoisted_2$1)) ], 16, _hoisted_1$3); } const IconStarOutline = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2]]); const _hoisted_1$2 = ["aria-selected", "tabindex"]; const _sfc_main$2 = /* @__PURE__ */ defineComponent({ __name: "NcAppSidebarTabsButton", props: /* @__PURE__ */ mergeModels({ tab: {} }, { "selected": { type: Boolean, ...{ required: true } }, "selectedModifiers": {} }), emits: ["update:selected"], setup(__props) { const selected = useModel(__props, "selected"); return (_ctx, _cache) => { return openBlock(), createElementBlock("button", { class: normalizeClass(["button-vue", [_ctx.$style.sidebarTabsButton, { [_ctx.$style.sidebarTabsButton_selected]: selected.value }]]), role: "tab", "aria-selected": selected.value, tabindex: selected.value ? 0 : -1, onClick: _cache[0] || (_cache[0] = ($event) => selected.value = true) }, [ createElementVNode("span", { class: normalizeClass(_ctx.$style.sidebarTabsButton__icon) }, [ createVNode(_sfc_main$6, { vnodes: _ctx.tab.renderIcon() }, { default: withCtx(() => [ createElementVNode("span", { class: normalizeClass([_ctx.$style.sidebarTabsButton__legacyIcon, _ctx.tab.icon]) }, null, 2) ]), _: 1 }, 8, ["vnodes"]) ], 2), createElementVNode("span", { class: normalizeClass(_ctx.$style.sidebarTabsButton__name) }, toDisplayString(_ctx.tab.name), 3) ], 10, _hoisted_1$2); }; } }); const sidebarTabsButton = "_sidebarTabsButton_1y2dv_20"; const sidebarTabsButton_selected = "_sidebarTabsButton_selected_1y2dv_45"; const sidebarTabsButton__name = "_sidebarTabsButton__name_1y2dv_59"; const sidebarTabsButton__icon = "_sidebarTabsButton__icon_1y2dv_70"; const sidebarTabsButton__legacyIcon = "_sidebarTabsButton__legacyIcon_1y2dv_76"; const style0 = { "material-design-icon": "_material-design-icon_1y2dv_12", sidebarTabsButton, sidebarTabsButton_selected, sidebarTabsButton__name, sidebarTabsButton__icon, sidebarTabsButton__legacyIcon }; const cssModules = { "$style": style0 }; const NcAppSidebarTabsButton = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__cssModules", cssModules]]); const _sfc_main$1 = { name: "NcAppSidebarTabs", components: { NcAppSidebarTabsButton }, provide() { return { registerTab: this.registerTab, unregisterTab: this.unregisterTab, // Getter as an alternative to Vue 2.7 computed(() => this.activeTab) getActiveTab: () => this.activeTab, // Used to check whether the tab header is shown so the tabs can reference the tab header for `aria-labelledby` or not isTablistShown: () => this.hasMultipleTabs }; }, props: { /** * Id of the tab to activate */ active: { type: String, default: "" }, /** * Force the tab navigation to display even if there is only one tab */ forceTabs: { type: Boolean, default: false } }, emits: ["update:active"], data(props) { return { /** * Tab descriptions from the passed NcSidebarTab components' props to build the tab navbar from. */ tabs: [], /** * Local active (open) tab's ID. It allows to use component without v-model:active */ activeTab: props.active }; }, computed: { /** * Has multiple tabs. If only one tab - its content is shown without navigation * * @return {boolean} */ hasMultipleTabs() { return this.tabs.length > 1; }, showForSingleTab() { return this.forceTabs && this.tabs.length === 1; }, currentTabIndex() { return this.tabs.findIndex((tab) => tab.id === this.activeTab); } }, watch: { tabs() { if (this.active) { this.updateActive(); } }, active(active) { if (active !== this.activeTab) { this.updateActive(); } } }, methods: { /** * Set the current active tab * * @param {string} id the id of the tab */ setActive(id) { this.activeTab = id; this.$emit("update:active", this.activeTab); }, /** * Focus the previous tab * and emit to the parent component */ focusPreviousTab() { if (this.currentTabIndex > 0) { this.setActive(this.tabs[this.currentTabIndex - 1].id); } this.focusActiveTab(); }, /** * Focus the next tab * and emit to the parent component */ focusNextTab() { if (this.currentTabIndex < this.tabs.length - 1) { this.setActive(this.tabs[this.currentTabIndex + 1].id); } this.focusActiveTab(); }, /** * Focus the first tab * and emit to the parent component */ focusFirstTab() { this.setActive(this.tabs[0].id); this.focusActiveTab(); }, /** * Focus the last tab * and emit to the parent component */ focusLastTab() { this.setActive(this.tabs[this.tabs.length - 1].id); this.focusActiveTab(); }, /** * Focus the current active tab */ focusActiveTab() { this.$el.querySelector(`#tab-button-${this.activeTab}`).focus(); }, /** * Focus the content on tab * see aria accessibility guidelines */ focusActiveTabContent() { this.$el.querySelector("#tab-" + this.activeTab).focus(); }, /** * Update the current active tab */ updateActive() { this.activeTab = this.active && this.tabs.some(({ id }) => id === this.active) ? this.active : this.tabs[0]?.id ?? ""; }, /** * Register child tab in the tabs * * @param {object} tab child tab passed to slot */ registerTab(tab) { this.tabs.push(tab); this.tabs.sort((a, b) => { if (a.order === b.order) { return a.name.localeCompare(b.name, [getCanonicalLocale()]); } return a.order - b.order; }); this.updateActive(); }, /** * Unregister child tab from the tabs * * @param {string} id tab's id */ unregisterTab(id) { const tabIndex = this.tabs.findIndex((tab) => tab.id === id); if (tabIndex !== -1) { this.tabs.splice(tabIndex, 1); } if (this.activeTab === id) { this.updateActive(); } } } }; const _hoisted_1$1 = { class: "app-sidebar-tabs" }; function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_NcAppSidebarTabsButton = resolveComponent("NcAppSidebarTabsButton"); return openBlock(), createElementBlock("div", _hoisted_1$1, [ $options.hasMultipleTabs || $options.showForSingleTab ? (openBlock(), createElementBlock("div", { key: 0, role: "tablist", class: "app-sidebar-tabs__nav", onKeydown: [ _cache[0] || (_cache[0] = withKeys(withModifiers((...args) => $options.focusPreviousTab && $options.focusPreviousTab(...args), ["exact", "prevent", "stop"]), ["left"])), _cache[1] || (_cache[1] = withKeys(withModifiers((...args) => $options.focusNextTab && $options.focusNextTab(...args), ["exact", "prevent", "stop"]), ["right"])), _cache[2] || (_cache[2] = withKeys(withModifiers((...args) => $options.focusActiveTabContent && $options.focusActiveTabContent(...args), ["exact", "prevent", "stop"]), ["tab"])), _cache[3] || (_cache[3] = withKeys(withModifiers((...args) => $options.focusFirstTab && $options.focusFirstTab(...args), ["exact", "prevent", "stop"]), ["home"])), _cache[4] || (_cache[4] = withKeys(withModifiers((...args) => $options.focusLastTab && $options.focusLastTab(...args), ["exact", "prevent", "stop"]), ["end"])), _cache[5] || (_cache[5] = withKeys(withModifiers((...args) => $options.focusFirstTab && $options.focusFirstTab(...args), ["exact", "prevent", "stop"]), ["page-up"])), _cache[6] || (_cache[6] = withKeys(withModifiers((...args) => $options.focusLastTab && $options.focusLastTab(...args), ["exact", "prevent", "stop"]), ["page-down"])) ] }, [ (openBlock(true), createElementBlock(Fragment, null, renderList($data.tabs, (tab) => { return openBlock(), createBlock(_component_NcAppSidebarTabsButton, { id: `tab-button-${tab.id}`, key: tab.id, class: "app-sidebar-tabs__tab", "aria-controls": `tab-${tab.id}`, selected: $data.activeTab === tab.id, tab, "onUpdate:selected": ($event) => $options.setActive(tab.id) }, null, 8, ["id", "aria-controls", "selected", "tab", "onUpdate:selected"]); }), 128)) ], 32)) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(["app-sidebar-tabs__content", { "app-sidebar-tabs__content--multiple": $options.hasMultipleTabs }]) }, [ renderSlot(_ctx.$slots, "default", {}, void 0, true) ], 2) ]); } const NcAppSidebarTabs = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1], ["__scopeId", "data-v-1e2d5bfb"]]); register(t15); const _sfc_main = { name: "NcAppSidebar", components: { NcActions, NcAppSidebarHeader: _sfc_main$7, NcAppSidebarTabs, NcButton, NcLoadingIcon, NcEmptyContent, IconArrowRight, IconClose, IconDockRight, IconStar, IconStarOutline }, directives: { Focus: directive, /** @type {import('vue').ObjectDirective} */ ClickOutside: vOnClickOutside }, inject: { ncContentSelector: { from: CONTENT_SELECTOR_KEY, default: void 0 } }, props: { /** * The active tab */ active: { type: String, default: "" }, /** * Main text of the sidebar */ name: { type: String, required: true }, /** * Allow to edit the sidebar name. */ nameEditable: { type: Boolean, default: false }, /** * Placeholder in the edit field if the name is editable. */ namePlaceholder: { type: String, default: "" }, /** * Secondary name of the sidebar (subline) */ subname: { type: String, default: "" }, /** * Title to display for the subname. */ subtitle: { type: String, default: "" }, /** * Url to the top header background image * Applied with css */ background: { type: String, default: "" }, /** * Enable the favourite icon if not null * See fired events */ starred: { type: Boolean, default: null }, /** * Show loading spinner instead of the star icon */ starLoading: { type: Boolean, default: false }, /** * Show loading spinner instead of tabs */ loading: { type: Boolean, default: false }, /** * Display the sidebar in compact mode */ compact: { type: Boolean, default: false }, /** * Only display close button and default slot content. * Don't display other header content and primary and secondary actions. * Useful when showing the EmptyContent component as content. */ empty: { type: Boolean, default: false }, /** * Force the actions to display in a three dot menu */ forceMenu: { type: Boolean, default: false }, /** * Force the tab navigation to display even if there is only one tab */ forceTabs: { type: Boolean, default: false }, /** * Linkify the name */ linkifyName: { type: Boolean, default: false }, /** * Title to display for the name. * Can be set to the same text in case it's too long. */ title: { type: String, default: "" }, /** * Allow to conditionally show the sidebar * You can also use `v-if` on the sidebar, but using the open prop allow to keep * the sidebar inside the DOM for performance if it is opened and closed multiple times. * * When using the `open` property to close the sidebar a built-in toggle button will be shown to reopen it, * similar to the app navigation. You can remove this button with the `no-toggle` prop. */ open: { type: Boolean, default: true }, /** * Custom classes to assign to the sidebar toggle button. * If needed this can be used to assign styles to the button using `:deep()` selector. */ toggleClasses: { type: [String, Array, Object], default: "" }, /** * Custom attrs to assign to the sidebar toggle button. */ toggleAttrs: { type: Object, default: void 0 }, /** * Do not add the built-in toggle button with `open` prop. */ noToggle: { type: Boolean, default: false } }, emits: [ "close", "closed", "opened", // 'figureClick', not emitted on purpose to make "hasFigureClickListener" work "update:active", "update:name", "update:nameEditable", "update:open", "update:starred", "submitName", "dismissEditing" ], setup() { const headerRef = ref(null); provide("NcAppSidebar:header:ref", headerRef); return { uid: createElementId(), isMobile: useIsSmallMobile(), headerRef }; }, data() { return { changeNameTranslated: t("Change name"), closeTranslated: t("Close sidebar"), favoriteTranslated: t("Favorite"), isStarred: this.starred, focusTrap: null, elementToReturnFocus: null }; }, computed: { canStar() { return this.isStarred !== null; }, hasFigureClickListener() { return !!this.$attrs.onFigureClick; } }, watch: { starred() { this.isStarred = this.starred; }, isMobile() { this.toggleFocusTrap(); }, open() { this.checkToggleButtonContainerAvailability(); } }, created() { this.preserveElementToReturnFocus(); this.checkToggleButtonContainerAvailability(); }, beforeUnmount() { this.$emit("closed"); this.focusTrap?.deactivate(); }, methods: { isSlotPopulated, t, preserveElementToReturnFocus() { if (document.activeElement && document.activeElement !== document.body) { this.elementToReturnFocus = document.activeElement; if (this.elementToReturnFocus.getAttribute("role") === "menuitem") { const menu = this.elementToReturnFocus.closest('[role="menu"]'); if (menu) { const menuTrigger = document.querySelector(`[aria-controls="${menu.id}"]`); this.elementToReturnFocus = menuTrigger; } } } }, initFocusTrap() { if (this.focusTrap) { return; } this.focusTrap = createFocusTrap([ // The sidebar itself this.$refs.sidebar, // Nextcloud Server header navigation document.querySelector("#header") ], { allowOutsideClick: true, fallbackFocus: this.$refs.closeButton.$el, trapStack: getTrapStack(), escapeDeactivates: false }); }, /** * Activate focus trap if it is currently needed, otherwise deactivate */ toggleFocusTrap() { if (this.open && this.isMobile) { this.initFocusTrap(); this.focusTrap.activate(); } else { this.focusTrap?.deactivate(); } }, /** * Close the sidebar on pressing the escape key on mobile * * @param {KeyboardEvent} event key down event */ onKeydownEsc(event) { if (this.isMobile) { event.stopPropagation(); this.closeSidebar(); } }, onAfterEnter(element) { if (this.elementToReturnFocus) { this.focus(); } this.toggleFocusTrap(); this.$emit("opened", element); }, onAfterLeave(element) { this.$emit("closed", element); this.toggleFocusTrap(); this.elementToReturnFocus?.focus({ focusVisible: true }); this.elementToReturnFocus = null; }, /** * Used to tell parent component the user asked to close the sidebar * * @param {Event} e close icon click event */ closeSidebar(e) { this.$emit("close", e); this.$emit("update:open", false); }, /** * Emit figure click event to parent component * * @param {Event} e click event */ onFigureClick(e) { this.$emit("figureClick", e); }, /** * Toggle the favourite state * and emit to the parent component */ toggleStarred() { this.isStarred = !this.isStarred; this.$emit("update:starred", this.isStarred); }, async editName() { this.$emit("update:nameEditable", true); if (this.nameEditable) { await this.$nextTick(); this.$refs.nameInput.focus(); } }, /** * Focus the sidebar * * @public */ focus() { if (!this.open && !this.noToggle) { this.$refs.toggle.$el.focus(); return; } try { this.headerRef.focus(); } catch { warn("NcAppSidebar should have focusable header for accessibility reasons. Use NcAppSidebarHeader component."); } }, /** * Focus the active tab * * @public */ focusActiveTabContent() { this.preserveElementToReturnFocus(); this.$refs.tabs.focusActiveTabContent(); }, /** * Check if the toggle button container is available */ checkToggleButtonContainerAvailability() { if (this.open === false && !this.noToggle && !this.ncContentSelector) { logger.warn("[NcAppSidebar] It looks like you want to use NcAppSidebar with the built-in toggle button. This feature is only available when NcAppSidebar is used in NcContent."); } }, /** * Emit name change event to parent component * * @param {Event} event input event */ onNameInput(event) { this.$emit("update:name", event.target.value); }, /** * Emit when the name form edit confirm button is pressed in order * to change the name. * * @param {Event} event submit event */ onSubmitName(event) { this.$emit("update:nameEditable", false); this.$emit("submitName", event); }, onDismissEditing() { this.$emit("update:nameEditable", false); this.$emit("dismissEditing"); }, onUpdateActive(activeTab) { this.$emit("update:active", activeTab); } } }; const _hoisted_1 = ["aria-labelledby"]; const _hoisted_2 = { class: "app-sidebar-header__info" }; const _hoisted_3 = { key: 0, class: "app-sidebar-header__tertiary-actions" }; const _hoisted_4 = { class: "app-sidebar-header__name-container" }; const _hoisted_5 = { class: "app-sidebar-header__mainname-container" }; const _hoisted_6 = ["placeholder", "value"]; const _hoisted_7 = ["title"]; const _hoisted_8 = { key: 2, class: "app-sidebar-header__description" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_IconDockRight = resolveComponent("IconDockRight"); const _component_NcButton = resolveComponent("NcButton"); const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon"); const _component_IconStar = resolveComponent("IconStar"); const _component_IconStarOutline = resolveComponent("IconStarOutline"); const _component_NcAppSidebarHeader = resolveComponent("NcAppSidebarHeader"); const _component_IconArrowRight = resolveComponent("IconArrowRight"); const _component_NcActions = resolveComponent("NcActions"); const _component_IconClose = resolveComponent("IconClose"); const _component_NcAppSidebarTabs = resolveComponent("NcAppSidebarTabs"); const _component_NcEmptyContent = resolveComponent("NcEmptyContent"); const _directive_focus = resolveDirective("focus"); const _directive_click_outside = resolveDirective("click-outside"); return openBlock(), createBlock(Transition, { appear: "", name: "slide-right", onAfterEnter: $options.onAfterEnter, onAfterLeave: $options.onAfterLeave }, { default: withCtx(() => [ withDirectives(createElementVNode("aside", { id: "app-sidebar-vue", ref: "sidebar", class: "app-sidebar", "aria-labelledby": `app-sidebar-vue-${$setup.uid}__header`, onKeydown: _cache[6] || (_cache[6] = withKeys((...args) => $options.onKeydownEsc && $options.onKeydownEsc(...args), ["esc"])) }, [ $options.ncContentSelector && !$props.open && !$props.noToggle ? (openBlock(), createBlock(Teleport, { key: 0, to: $options.ncContentSelector }, [ createVNode(_component_NcButton, mergeProps({ ref: "toggle", "aria-label": $options.t("Open sidebar"), class: ["app-sidebar__toggle", $props.toggleClasses], variant: "tertiary" }, $props.toggleAttrs, { onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("update:open", true)) }), { icon: withCtx(() => [ renderSlot(_ctx.$slots, "toggle-icon", {}, () => [ createVNode(_component_IconDockRight, { size: 20 }) ], true) ]), _: 3 }, 16, ["aria-label", "class"]) ], 8, ["to"])) : createCommentVNode("", true), createElementVNode("header", { class: normalizeClass(["app-sidebar-header", { "app-sidebar-header--with-figure": $options.isSlotPopulated(_ctx.$slots.header?.()) || $props.background, "app-sidebar-header--compact": $props.compact }]) }, [ !$props.empty ? renderSlot(_ctx.$slots, "info", { key: 0 }, () => [ createElementVNode("div", _hoisted_2, [ $options.isSlotPopulated(_ctx.$slots.header?.()) || $props.background ? (openBlock(), createElementBlock("div", { key: 0, class: normalizeClass(["app-sidebar-header__figure", { "app-sidebar-header__figure--with-action": $options.hasFigureClickListener }]), style: normalizeStyle({ backgroundImage: `url(${$props.background})` }), tabindex: "0", onClick: _cache[1] || (_cache[1] = (...args) => $options.onFigureClick && $options.onFigureClick(...args)), onKeydown: _cache[2] || (_cache[2] = withKeys((...args) => $options.onFigureClick && $options.onFigureClick(...args), ["enter"])) }, [ renderSlot(_ctx.$slots, "header", { class: "app-sidebar-header__background" }, void 0, true) ], 38)) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(["app-sidebar-header__desc", { "app-sidebar-header__desc--with-tertiary-action": $options.canStar || $options.isSlotPopulated(_ctx.$slots["tertiary-actions"]?.()), "app-sidebar-header__desc--editable": $props.nameEditable && !$props.subname, "app-sidebar-header__desc--with-subname--editable": $props.nameEditable && $props.subname, "app-sidebar-header__desc--without-actions": !$options.isSlotPopulated(_ctx.$slots["secondary-actions"]?.()) }]) }, [ $options.canStar || $options.isSlotPopulated(_ctx.$slots["tertiary-actions"]?.()) ? (openBlock(), createElementBlock("div", _hoisted_3, [ renderSlot(_ctx.$slots, "tertiary-actions", {}, () => [ $options.canStar ? (openBlock(), createBlock(_component_NcButton, { key: 0, "aria-label": $data.favoriteTranslated, pressed: $data.isStarred, class: "app-sidebar-header__star", variant: "secondary", onClick: withModifiers($options.toggleStarred, ["prevent"]) }, { icon: withCtx(() => [ $props.starLoading ? (openBlock(), createBlock(_component_NcLoadingIcon, { key: 0 })) : $data.isStarred ? (openBlock(), createBlock(_component_IconStar, { key: 1, size: 20 })) : (openBlock(), createBlock(_component_IconStarOutline, { key: 2, size: 20 })) ]), _: 1 }, 8, ["aria-label", "pressed", "onClick"])) : createCommentVNode("", true) ], true) ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_4, [ createElementVNode("div", _hoisted_5, [ withDirectives(createVNode(_component_NcAppSidebarHeader, { class: "app-sidebar-header__mainname", name: $props.name, linkify: $props.linkifyName, title: $props.title, tabindex: $props.nameEditable ? 0 : -1, onClick: withModifiers($options.editName, ["self"]) }, null, 8, ["name", "linkify", "title", "tabindex", "onClick"]), [ [vShow, !$props.nameEditable] ]), $props.nameEditable ? withDirectives((openBlock(), createElementBlock("form", { key: 0, class: "app-sidebar-header__mainname-form", onSubmit: _cache[5] || (_cache[5] = withModifiers((...args) => $options.onSubmitName && $options.onSubmitName(...args), ["prevent"])) }, [ withDirectives(createElementVNode("input", { ref: "nameInput", class: "app-sidebar-header__mainname-input", type: "text", placeholder: $props.namePlaceholder, value: $props.name, onKeydown: _cache[3] || (_cache[3] = withKeys(withModifiers((...args) => $options.onDismissEditing && $options.onDismissEditing(...args), ["stop"]), ["esc"])), onInput: _cache[4] || (_cache[4] = (...args) => $options.onNameInput && $options.onNameInput(...args)) }, null, 40, _hoisted_6), [ [_directive_focus] ]), createVNode(_component_NcButton, { "aria-label": $data.changeNameTranslated, type: "submit", variant: "tertiary-no-background" }, { icon: withCtx(() => [ createVNode(_component_IconArrowRight, { size: 20 }) ]), _: 1 }, 8, ["aria-label"]) ], 32)), [ [_directive_click_outside, () => $options.onSubmitName()] ]) : createCommentVNode("", true), $options.isSlotPopulated(_ctx.$slots["secondary-actions"]?.()) ? (openBlock(), createBlock(_component_NcActions, { key: 1, class: "app-sidebar-header__menu", "force-menu": $props.forceMenu }, { default: withCtx(() => [ renderSlot(_ctx.$slots, "secondary-actions", {}, void 0, true) ]), _: 3 }, 8, ["force-menu"])) : createCommentVNode("", true) ]), $props.subname.trim() !== "" || _ctx.$slots["subname"] ? (openBlock(), createElementBlock("p", { key: 0, title: $props.subtitle || void 0, class: "app-sidebar-header__subname" }, [ renderSlot(_ctx.$slots, "subname", {}, () => [ createTextVNode(toDisplayString($props.subname), 1) ], true) ], 8, _hoisted_7)) : createCommentVNode("", true) ]) ], 2) ]) ], true) : (openBlock(), createBlock(_component_NcAppSidebarHeader, { key: 1, class: "app-sidebar-header__mainname--hidden", name: $props.name, tabindex: "-1" }, null, 8, ["name"])), createVNode(_component_NcButton, { ref: "closeButton", "aria-label": $data.closeTranslated, title: $data.closeTranslated, class: "app-sidebar__close", variant: "tertiary", onClick: withModifiers($options.closeSidebar, ["prevent"]) }, { icon: withCtx(() => [ createVNode(_component_IconClose, { size: 20 }) ]), _: 1 }, 8, ["aria-label", "title", "onClick"]), $options.isSlotPopulated(_ctx.$slots.description?.()) && !$props.empty ? (openBlock(), createElementBlock("div", _hoisted_8, [ renderSlot(_ctx.$slots, "description", {}, void 0, true) ])) : createCommentVNode("", true) ], 2), withDirectives(createVNode(_component_NcAppSidebarTabs, { ref: "tabs", active: $props.active, "force-tabs": $props.forceTabs, "onUpdate:active": $options.onUpdateActive }, { default: withCtx(() => [ renderSlot(_ctx.$slots, "default", {}, void 0, true) ]), _: 3 }, 8, ["active", "force-tabs", "onUpdate:active"]), [ [vShow, !$props.loading] ]), $props.loading ? (openBlock(), createBlock(_component_NcEmptyContent, { key: 1 }, { icon: withCtx(() => [ createVNode(_component_NcLoadingIcon, { size: 64 }) ]), _: 1 })) : createCommentVNode("", true) ], 40, _hoisted_1), [ [vShow, $props.open] ]) ]), _: 3 }, 8, ["onAfterEnter", "onAfterLeave"]); } const NcAppSidebar = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-104e67d6"]]); export { NcAppSidebar as N }; //# sourceMappingURL=NcAppSidebar-BvBvQsXb.mjs.map