UNPKG

@nextcloud/vue

Version:
642 lines (641 loc) 21.8 kB
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