@nextcloud/vue
Version:
Nextcloud vue components
1,047 lines (1,046 loc) • 36.7 kB
JavaScript
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