@nextcloud/vue
Version:
Nextcloud vue components
281 lines (280 loc) • 8.19 kB
JavaScript
import '../assets/NcButton-CfOAX-eQ.css';
import { n as normalizeComponent } from "../chunks/_plugin-vue2_normalizer-DU4iP6Vu.mjs";
const _sfc_main = {
name: "NcButton",
inject: {
getNcPopoverTriggerAttrs: {
from: "NcPopover:trigger:attrs",
default: () => () => ({})
}
},
props: {
/**
* Set the text and icon alignment
*
* @default 'center'
*/
alignment: {
type: String,
default: "center",
validator: (alignment) => ["start", "start-reverse", "center", "center-reverse", "end", "end-reverse"].includes(alignment)
},
/**
* Toggles the disabled state of the button on and off.
*/
disabled: {
type: Boolean,
default: false
},
/**
* Specify the button size
* Accepted values: `'small'`, `'normal'` (default), `'large'`
*/
size: {
type: String,
default: "normal",
validator(value) {
return ["small", "normal", "large"].includes(value);
}
},
/**
* Specifies the button type
* Accepted values: primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success. If left empty,
* the default button style will be applied.
*/
type: {
type: String,
validator(value) {
return ["primary", "secondary", "tertiary", "tertiary-no-background", "tertiary-on-primary", "error", "warning", "success"].includes(value);
},
default: "secondary"
},
/**
* Specifies the button native type
* Accepted values: submit, reset, button. If left empty,
* the default "button" type will be used.
*/
nativeType: {
type: String,
validator(value) {
return ["submit", "reset", "button"].indexOf(value) !== -1;
},
default: "button"
},
/**
* Specifies whether the button should span all the available width.
* By default, buttons span the whole width of the container.
*/
wide: {
type: Boolean,
default: false
},
/**
* Always try to provide an aria-label to your button. Make it more
* specific than the button's name by provide some more context. E.g. if
* the name of the button is "send" in the Mail app, the aria label could
* be "Send email".
*/
ariaLabel: {
type: String,
default: null
},
/**
* Providing the href attribute turns the button component into an `a`
* element.
*/
href: {
type: String,
default: null
},
/**
* Target for the `a` element if `href` is set.
*/
target: {
type: String,
default: "_self"
},
/**
* Providing the download attribute with href downloads file when clicking.
*/
download: {
type: String,
default: null
},
/**
* Providing the to attribute turns the button component into a `router-link`
* element. Takes precedence over the href attribute.
*/
to: {
type: [String, Object],
default: null
},
/**
* Pass in `true` if you want the matching behaviour of `router-link` to
* be non-inclusive: https://router.vuejs.org/api/#exact
*/
exact: {
type: Boolean,
default: false
},
/**
* @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.
* @todo Add a check in @nextcloud/vue 9 that this prop is not provided,
* otherwise root element will inherit incorrect aria-hidden.
*/
ariaHidden: {
type: Boolean,
default: null
},
/**
* The pressed state of the button if it has a checked state
* This will add the `aria-pressed` attribute and for the button to have the primary style in checked state.
*
* Pressed state is not supported for links
*/
pressed: {
type: Boolean,
default: null
}
},
emits: ["update:pressed", "click"],
computed: {
/**
* The real type to be used for the button, enforces `primary` for pressed state and, if stateful button, any other type for not pressed state
* Otherwise the type property is used.
*/
realType() {
if (this.pressed) {
return "primary";
}
if (this.pressed === false && this.type === "primary") {
return "secondary";
}
return this.type;
},
/**
* The flexbox alignment of the button content
*/
flexAlignment() {
return this.alignment.split("-")[0];
},
/**
* If the button content should be reversed (icon on the end)
*/
isReverseAligned() {
return this.alignment.includes("-");
},
ncPopoverTriggerAttrs() {
return this.getNcPopoverTriggerAttrs();
}
},
/**
* The render function to display the component
*
* @param {Function} h The function to create VNodes
* @return {object|undefined} The created VNode
*/
render(h) {
const hasText = !!this.$slots.default;
const hasIcon = this.$slots?.icon;
if (!hasText && !this.ariaLabel) {
console.warn(
"You need to fill either the text or the ariaLabel props in the button component.",
{
text: this.$slots.default?.[0]?.text,
ariaLabel: this.ariaLabel
},
this
);
}
const isLink = this.to || this.href;
const hasPressed = !isLink && typeof this.pressed === "boolean";
const renderButton = ({ href, navigate, isActive, isExactActive } = {}) => h(
isLink ? "a" : "button",
{
class: [
"button-vue",
`button-vue--size-${this.size}`,
{
"button-vue--icon-only": hasIcon && !hasText,
"button-vue--text-only": hasText && !hasIcon,
"button-vue--icon-and-text": hasIcon && hasText,
[`button-vue--vue-${this.realType}`]: this.realType,
"button-vue--wide": this.wide,
[`button-vue--${this.flexAlignment}`]: this.flexAlignment !== "center",
"button-vue--reverse": this.isReverseAligned,
active: isActive,
"router-link-exact-active": isExactActive
}
],
attrs: {
"aria-label": this.ariaLabel,
"aria-pressed": hasPressed ? this.pressed.toString() : void 0,
disabled: this.disabled,
type: isLink ? null : this.nativeType,
role: isLink ? "button" : null,
href: this.to ? href : this.href || null,
target: isLink ? this.target || "_self" : null,
rel: isLink ? "nofollow noreferrer noopener" : null,
download: !this.to && this.href && this.download ? this.download : null,
// If this button is used as a popover trigger, we need to apply trigger attrs, e.g. aria attributes
...this.ncPopoverTriggerAttrs,
// Inherit all the component attrs
...this.$attrs
},
on: {
...this.$listeners,
click: ($event) => {
if (hasPressed) {
this.$emit("update:pressed", !this.pressed);
}
this.$emit("click", $event);
navigate?.($event);
}
}
},
[
h("span", { class: "button-vue__wrapper" }, [
hasIcon ? h(
"span",
{
class: "button-vue__icon",
attrs: {
"aria-hidden": "true"
}
},
[this.$slots.icon]
) : null,
hasText ? h("span", { class: "button-vue__text" }, [this.$slots.default]) : null
])
]
);
if (this.to) {
return h("router-link", {
props: {
custom: true,
to: this.to,
exact: this.exact
},
scopedSlots: {
default: renderButton
}
});
}
return renderButton();
}
};
const _sfc_render = null;
const _sfc_staticRenderFns = null;
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns,
false,
null,
"b2be1481"
);
const NcButton = __component__.exports;
export {
NcButton as default
};