@nextcloud/vue
Version:
Nextcloud vue components
642 lines (641 loc) • 21.8 kB
JavaScript
import '../assets/NcAppNavigationItem-D97Onpd9.css';
import { createElementBlock, openBlock, mergeProps, createElementVNode, createCommentVNode, toDisplayString, resolveComponent, createBlock, normalizeClass, withCtx, resolveDynamicComponent, normalizeProps, guardReactiveProps, renderSlot, withKeys, withModifiers, createVNode, createTextVNode } from "vue";
import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.mjs";
import { C as ChevronDown } from "./ChevronDown-FiGpp0KT.mjs";
import { C as ChevronUp } from "./ChevronUp-DPXFp1ss.mjs";
import { r as register, v as t21, a as t, w as t50, x as t23 } from "./_l10n-DrTiip5c.mjs";
import { N as NcButton } from "./NcButton-Dc8V4Urj.mjs";
import { N as NcInputConfirmCancel } from "./NcInputConfirmCancel-CSO9hp4z.mjs";
import { useIsMobile } from "../composables/useIsMobile/index.mjs";
import { c as createElementId } from "./createElementId-DhjFt1I9.mjs";
import { N as NcActionButton } from "./NcActionButton-pKOSrlGE.mjs";
import { N as NcActions } from "./NcActions-DWmvh7-Y.mjs";
import { N as NcLoadingIcon } from "./NcLoadingIcon-b_ajZ_nQ.mjs";
import { _ as _sfc_main$4 } from "./NcVNodes.vue_vue_type_script_lang-BqUHinRZ.mjs";
const _sfc_main$3 = {
name: "PencilIcon",
emits: ["click"],
props: {
title: {
type: String
},
fillColor: {
type: String,
default: "currentColor"
},
size: {
type: Number,
default: 24
}
}
};
const _hoisted_1$2 = ["aria-hidden", "aria-label"];
const _hoisted_2$2 = ["fill", "width", "height"];
const _hoisted_3$2 = { d: "M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z" };
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 pencil-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$2);
}
const Pencil = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3]]);
const _sfc_main$2 = {
name: "UndoIcon",
emits: ["click"],
props: {
title: {
type: String
},
fillColor: {
type: String,
default: "currentColor"
},
size: {
type: Number,
default: 24
}
}
};
const _hoisted_1$1 = ["aria-hidden", "aria-label"];
const _hoisted_2$1 = ["fill", "width", "height"];
const _hoisted_3$1 = { d: "M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z" };
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 undo-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$1);
}
const Undo = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
register(t21);
const _sfc_main$1 = {
name: "NcAppNavigationIconCollapsible",
components: {
NcButton,
ChevronDown,
ChevronUp
},
props: {
/**
* Is the list currently open (or collapsed)
*/
open: {
type: Boolean,
required: true
},
/**
* Is the navigation item currently active.
*/
active: {
type: Boolean,
required: true
}
},
emits: ["click"],
computed: {
labelButton() {
return this.open ? t("Collapse menu") : t("Open menu");
}
},
methods: {
onClick(e) {
this.$emit("click", e);
}
}
};
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
const _component_ChevronUp = resolveComponent("ChevronUp");
const _component_ChevronDown = resolveComponent("ChevronDown");
const _component_NcButton = resolveComponent("NcButton");
return openBlock(), createBlock(_component_NcButton, {
class: normalizeClass(["icon-collapse", {
"icon-collapse--active": $props.active,
"icon-collapse--open": $props.open
}]),
"aria-label": $options.labelButton,
variant: $props.active ? "tertiary-on-primary" : "tertiary",
onClick: $options.onClick
}, {
icon: withCtx(() => [
$props.open ? (openBlock(), createBlock(_component_ChevronUp, {
key: 0,
size: 20
})) : (openBlock(), createBlock(_component_ChevronDown, {
key: 1,
size: 20
}))
]),
_: 1
}, 8, ["class", "aria-label", "variant", "onClick"]);
}
const NcAppNavigationIconCollapsible = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1], ["__scopeId", "data-v-e6236e50"]]);
register(t23, t50);
const _sfc_main = {
name: "NcAppNavigationItem",
components: {
NcActions,
NcActionButton,
NcAppNavigationIconCollapsible,
NcInputConfirmCancel,
NcLoadingIcon,
NcVNodes: _sfc_main$4,
Pencil,
Undo
},
props: {
/**
* If you are not using vue-router you can use the property to set this item as the active navigation entry.
* When using vue-router and the `to` property this is set automatically.
*/
active: {
type: Boolean,
default: false
},
/**
* The main text content of the entry.
*/
name: {
type: String,
required: true
},
/**
* The title attribute of the element.
*/
title: {
type: String,
default: null
},
/**
* id attribute of the list item element
*/
id: {
type: String,
default: () => createElementId(),
validator: (id) => id.trim() !== ""
},
/**
* Refers to the icon on the left, this prop accepts a class
* like 'icon-category-enabled'.
*/
icon: {
type: String,
default: ""
},
/**
* Displays a loading animated icon on the left of the element
* instead of the icon.
*/
loading: {
type: Boolean,
default: false
},
/**
* Passing in a route will make the root element of this
* component a `<router-link />` that points to that route.
* By leaving this blank, the root element will be a `<li>`.
*/
to: {
type: [String, Object],
default: null
},
/**
* A direct link. This will be used as the `href` attribute.
* This will ignore any `to` prop being defined.
*/
href: {
type: String,
default: null
},
/**
* Gives the possibility to collapse the children elements into the
* parent element (true) or expands the children elements (false).
*/
allowCollapse: {
type: Boolean,
default: false
},
/**
* Makes the name of the item editable by providing an `ActionButton`
* component that toggles a form
*/
editable: {
type: Boolean,
default: false
},
/**
* Only for 'editable' items, sets label for the edit action button.
*/
editLabel: {
type: String,
default: ""
},
/**
* Only for items in 'editable' mode, sets the placeholder text for the editing form.
*/
editPlaceholder: {
type: String,
default: ""
},
/**
* Pins the item to the bottom left area, above the settings. Do not
* place 'non-pinned' `AppnavigationItem` components below `pinned`
* ones.
*/
pinned: {
type: Boolean,
default: false
},
/**
* Puts the item in the 'undo' state.
*/
undo: {
type: Boolean,
default: false
},
/**
* The navigation collapsible state (synced)
*/
open: {
type: Boolean,
default: false
},
/**
* The actions menu open state (synced)
*/
menuOpen: {
type: Boolean,
default: false
},
/**
* Force the actions to display in a three dot menu
*/
forceMenu: {
type: Boolean,
default: false
},
/**
* The action's menu default icon
*/
menuIcon: {
type: String,
default: void 0
},
/**
* The action's menu direction
*/
menuPlacement: {
type: String,
default: "bottom"
},
/**
* Entry aria details
*/
ariaDescription: {
type: String,
default: null
},
/**
* To be used only when the elements in the actions menu are very important
*/
forceDisplayActions: {
type: Boolean,
default: false
},
/**
* Number of action items outside the menu
*/
inlineActions: {
type: Number,
default: 0
}
},
emits: [
"update:menuOpen",
"update:open",
"update:name",
"click",
"undo"
],
setup() {
return {
isMobile: useIsMobile()
};
},
data() {
return {
actionsBoundariesElement: void 0,
editingValue: "",
opened: this.open,
// Collapsible state
editingActive: false,
/**
* Tracks the open state of the actions menu
*/
menuOpenLocalValue: false,
focused: false
};
},
computed: {
isRouterLink() {
return this.to && !this.href;
},
// Checks if the component is already a children of another
// instance of AppNavigationItem
canHaveChildren() {
if (this.$parent.$options._componentTag === "AppNavigationItem") {
return false;
} else {
return true;
}
},
editButtonAriaLabel() {
return this.editLabel ? this.editLabel : t("Edit item");
},
undoButtonAriaLabel() {
return t("Undo changes");
}
},
watch: {
open(newVal) {
this.opened = newVal;
}
},
mounted() {
this.actionsBoundariesElement = document.querySelector("#content-vue") || void 0;
},
methods: {
// sync opened menu state with prop
onMenuToggle(state) {
this.$emit("update:menuOpen", state);
this.menuOpenLocalValue = state;
},
// toggle the collapsible state
toggleCollapse() {
this.opened = !this.opened;
this.$emit("update:open", this.opened);
},
/**
* Handle link click
*
* @param {PointerEvent} event - Native click event
* @param {Function} [navigate] - VueRouter link's navigate if any
* @param {string} [routerLinkHref] - VueRouter link's href
*/
onClick(event, navigate, routerLinkHref) {
this.$emit("click", event);
if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
return;
}
if (routerLinkHref) {
navigate?.(event);
event.preventDefault();
}
},
// Edition methods
handleEdit() {
this.editingValue = this.name;
this.editingActive = true;
this.onMenuToggle(false);
this.$nextTick(() => {
this.$refs.editingInput.focusInput();
});
},
cancelEditing() {
this.editingActive = false;
},
handleEditingDone() {
this.$emit("update:name", this.editingValue);
this.editingValue = "";
this.editingActive = false;
},
// Undo methods
handleUndo() {
this.$emit("undo");
},
/**
* Show actions upon focus
*/
handleFocus() {
this.focused = true;
},
handleBlur() {
this.focused = false;
},
/**
* This method checks if the root element of the component is focused and
* if that's the case it focuses the actions button if available
*
* @param {Event} e the keydown event
*/
handleTab(e) {
if (!this.$refs.actions) {
return;
}
if (this.focused) {
e.preventDefault();
this.$refs.actions.$refs.triggerButton.$el.focus();
this.focused = false;
} else {
this.$refs.actions.$refs.triggerButton.$el.blur();
}
},
/**
* Is this an external link
*
* @param {string} href The link to check
* @return {boolean} Whether it is external or not
*/
isExternal(href) {
return href && href.match(/[a-z]+:\/\//i);
}
}
};
const _hoisted_1 = ["id"];
const _hoisted_2 = ["aria-current", "aria-description", "aria-expanded", "href", "target", "title", "onClick"];
const _hoisted_3 = {
key: 0,
class: "editingContainer"
};
const _hoisted_4 = {
key: 1,
class: "app-navigation-entry__deleted"
};
const _hoisted_5 = { class: "app-navigation-entry__deleted-description" };
const _hoisted_6 = {
key: 0,
class: "app-navigation-entry__counter-wrapper"
};
const _hoisted_7 = {
key: 0,
class: "app-navigation-entry__children"
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
const _component_NcInputConfirmCancel = resolveComponent("NcInputConfirmCancel");
const _component_Pencil = resolveComponent("Pencil");
const _component_NcActionButton = resolveComponent("NcActionButton");
const _component_Undo = resolveComponent("Undo");
const _component_NcActions = resolveComponent("NcActions");
const _component_NcAppNavigationIconCollapsible = resolveComponent("NcAppNavigationIconCollapsible");
return openBlock(), createElementBlock("li", {
id: $props.id,
class: normalizeClass([{
"app-navigation-entry--opened": $data.opened,
"app-navigation-entry--pinned": $props.pinned,
"app-navigation-entry--collapsible": $props.allowCollapse && !!_ctx.$slots.default
}, "app-navigation-entry-wrapper"])
}, [
(openBlock(), createBlock(resolveDynamicComponent($options.isRouterLink ? "router-link" : "NcVNodes"), normalizeProps(guardReactiveProps({ ...$options.isRouterLink && { custom: true, to: $props.to } })), {
default: withCtx(({ href: routerLinkHref, navigate, isActive }) => [
createElementVNode("div", {
class: normalizeClass(["app-navigation-entry", {
"app-navigation-entry--editing": $data.editingActive,
"app-navigation-entry--deleted": $props.undo,
active: $props.to && isActive || $props.active
}])
}, [
!$props.undo ? (openBlock(), createElementBlock("a", {
key: 0,
class: "app-navigation-entry-link",
"aria-current": $props.active || $props.to && isActive ? "page" : void 0,
"aria-description": $props.ariaDescription,
"aria-expanded": !!_ctx.$slots.default ? $data.opened.toString() : void 0,
href: $props.href || routerLinkHref || "#",
target: $options.isExternal($props.href) ? "_blank" : void 0,
title: $props.title || $props.name,
onBlur: _cache[1] || (_cache[1] = (...args) => $options.handleBlur && $options.handleBlur(...args)),
onClick: ($event) => $options.onClick($event, navigate, routerLinkHref),
onFocus: _cache[2] || (_cache[2] = (...args) => $options.handleFocus && $options.handleFocus(...args)),
onKeydown: _cache[3] || (_cache[3] = withKeys(withModifiers((...args) => $options.handleTab && $options.handleTab(...args), ["exact"]), ["tab"]))
}, [
createElementVNode("div", {
class: normalizeClass(["app-navigation-entry-icon", { [$props.icon]: $props.icon }])
}, [
$props.loading ? (openBlock(), createBlock(_component_NcLoadingIcon, { key: 0 })) : renderSlot(_ctx.$slots, "icon", {
key: 1,
active: $props.active || $props.to && isActive
}, void 0, true)
], 2),
createElementVNode("span", {
class: normalizeClass(["app-navigation-entry__name", { "hidden-visually": $data.editingActive }])
}, toDisplayString($props.name), 3),
$data.editingActive ? (openBlock(), createElementBlock("div", _hoisted_3, [
createVNode(_component_NcInputConfirmCancel, {
ref: "editingInput",
modelValue: $data.editingValue,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.editingValue = $event),
placeholder: $props.editPlaceholder !== "" ? $props.editPlaceholder : $props.name,
primary: $props.to && isActive || $props.active,
onCancel: $options.cancelEditing,
onConfirm: $options.handleEditingDone
}, null, 8, ["modelValue", "placeholder", "primary", "onCancel", "onConfirm"])
])) : createCommentVNode("", true)
], 40, _hoisted_2)) : createCommentVNode("", true),
$props.undo ? (openBlock(), createElementBlock("div", _hoisted_4, [
createElementVNode("div", _hoisted_5, toDisplayString($props.name), 1)
])) : createCommentVNode("", true),
(!!_ctx.$slots.actions || !!_ctx.$slots.counter || $props.editable || $props.undo) && !$data.editingActive ? (openBlock(), createElementBlock("div", {
key: 2,
class: normalizeClass(["app-navigation-entry__utils", { "app-navigation-entry__utils--display-actions": $props.forceDisplayActions || $data.menuOpenLocalValue || $props.menuOpen }])
}, [
!!_ctx.$slots.counter ? (openBlock(), createElementBlock("div", _hoisted_6, [
renderSlot(_ctx.$slots, "counter", {}, void 0, true)
])) : createCommentVNode("", true),
!!_ctx.$slots.actions || $props.editable && !$data.editingActive || $props.undo ? (openBlock(), createBlock(_component_NcActions, {
key: 1,
ref: "actions",
class: "app-navigation-entry__actions",
container: "#app-navigation-vue",
"boundaries-element": $data.actionsBoundariesElement,
inline: $props.inlineActions,
placement: $props.menuPlacement,
open: $props.menuOpen,
"force-menu": $props.forceMenu,
"default-icon": $props.menuIcon,
variant: $props.to && isActive || $props.active ? "tertiary-on-primary" : "tertiary",
"onUpdate:open": $options.onMenuToggle
}, {
icon: withCtx(() => [
renderSlot(_ctx.$slots, "menu-icon", {}, void 0, true)
]),
default: withCtx(() => [
$props.editable && !$data.editingActive ? (openBlock(), createBlock(_component_NcActionButton, {
key: 0,
"aria-label": $options.editButtonAriaLabel,
onClick: $options.handleEdit
}, {
icon: withCtx(() => [
createVNode(_component_Pencil, { size: 20 })
]),
default: withCtx(() => [
createTextVNode(" " + toDisplayString($props.editLabel), 1)
]),
_: 1
}, 8, ["aria-label", "onClick"])) : createCommentVNode("", true),
$props.undo ? (openBlock(), createBlock(_component_NcActionButton, {
key: 1,
"aria-label": $options.undoButtonAriaLabel,
onClick: $options.handleUndo
}, {
icon: withCtx(() => [
createVNode(_component_Undo, { size: 20 })
]),
_: 1
}, 8, ["aria-label", "onClick"])) : createCommentVNode("", true),
renderSlot(_ctx.$slots, "actions", {}, void 0, true)
]),
_: 2
}, 1032, ["boundaries-element", "inline", "placement", "open", "force-menu", "default-icon", "variant", "onUpdate:open"])) : createCommentVNode("", true)
], 2)) : createCommentVNode("", true),
$props.allowCollapse && !!_ctx.$slots.default ? (openBlock(), createBlock(_component_NcAppNavigationIconCollapsible, {
key: 3,
active: $props.to && isActive || $props.active,
open: $data.opened,
onClick: withModifiers($options.toggleCollapse, ["prevent", "stop"])
}, null, 8, ["active", "open", "onClick"])) : createCommentVNode("", true),
renderSlot(_ctx.$slots, "extra", {}, void 0, true)
], 2)
]),
_: 3
}, 16)),
$options.canHaveChildren && !!_ctx.$slots.default ? (openBlock(), createElementBlock("ul", _hoisted_7, [
renderSlot(_ctx.$slots, "default", {}, void 0, true)
])) : createCommentVNode("", true)
], 10, _hoisted_1);
}
const NcAppNavigationItem = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-d600f829"]]);
export {
NcAppNavigationItem as N
};
//# sourceMappingURL=NcAppNavigationItem-hKUS0nZj.mjs.map