UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

292 lines (291 loc) 8.52 kB
"use strict"; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); const vue = require("vue"); const common_utils = require("../../common/utils.cjs"); const button_constants = require("./button_constants.cjs"); const _pluginVue_exportHelper = require("../../_virtual/_plugin-vue_export-helper.cjs"); const link_constants = require("../link/link_constants.cjs"); const _sfc_main = { compatConfig: { MODE: 3 }, name: "DtButton", props: { /** * Whether the button is a circle or not. * @values true, false */ circle: { type: Boolean, default: false }, /** * The position of the icon slot within the button. * @values left, right, top, bottom */ iconPosition: { type: String, default: "left", validator: (position) => Object.keys(button_constants.ICON_POSITION_MODIFIERS).includes(position) }, /** * The fill and outline of the button associated with its visual importance. * @values clear, outlined, primary */ importance: { type: String, default: "primary", validator: (i) => Object.keys(button_constants.BUTTON_IMPORTANCE_MODIFIERS).includes(i) }, /** * Whether the button should be styled as a link or not. * @values true, false * @see DtLink */ link: { type: Boolean, default: false }, /** * The color of the link and button if the button is styled as a link. * @values default, warning, danger, success, muted * @see DtLink */ linkKind: { type: String, default: "default", validator: (lk) => Object.keys(link_constants.LINK_KIND_MODIFIERS).includes(lk) }, /** * Determines whether the link should have inverted styling if the button is styled as a link. * @values true, false * @see DtLink */ linkInverted: { type: Boolean, default: false }, /** * HTML button disabled attribute * <a class="d-link" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#disabled" target="_blank"> (Reference) </a> * @values true, false */ disabled: { type: Boolean, default: false }, /** * HTML button type attribute * <a * class="d-link" * href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type" * target="_blank" * > * (Reference) * </a> * @values button, submit, reset */ type: { type: String, default: "button", validator: (t) => button_constants.BUTTON_TYPES.includes(t) }, /** * Button width, accepts * <a class="d-link" href="https://developer.mozilla.org/en-US/docs/Web/CSS/width" target="_blank"> * CSS width attribute * </a> * values */ width: { type: String, default: null }, /** * The size of the button. * @values xs, sm, md, lg, xl */ size: { type: String, default: "md", validator: (s) => Object.keys(button_constants.BUTTON_SIZE_MODIFIERS).includes(s) }, /** * Used to customize the label container */ labelClass: { type: [String, Array, Object], default: "" }, /** * Whether the button should display a loading animation or not. * @values true, false */ loading: { type: Boolean, default: false }, /** * The color of the button. * @values default, muted, danger, inverted */ kind: { type: String, default: "default", validator: (k) => Object.keys(button_constants.BUTTON_KIND_MODIFIERS).includes(k) }, /** * Determines whether a screenreader reads live updates of * the button content to the user while the button * is in focus. default is to not. * @values true, false */ assertiveOnFocus: { type: Boolean, default: false }, /** * Determines whether the button should have active styling * default is false. * @values true, false */ active: { type: Boolean, default: false } }, emits: [ /** * Native button focus in event * * @event focusin * @type {FocusEvent} */ "focusin", /** * Native button focus out event * * @event focusout * @type {FocusEvent} */ "focusout" ], data() { return { ICON_POSITION_MODIFIERS: button_constants.ICON_POSITION_MODIFIERS, // whether the button is currently in focus isInFocus: false, hasSlotContent: common_utils.hasSlotContent }; }, computed: { buttonListeners() { return { focusin: (e) => { this.isInFocus = this.assertiveOnFocus; this.$emit("focusin", e); }, focusout: (e) => { this.isInFocus = false; this.$emit("focusout", e); } }; }, computedAriaLive() { return this.assertiveOnFocus && this.isInFocus ? "assertive" : this.$attrs.ariaLive; }, iconSize() { return button_constants.BUTTON_ICON_SIZES[this.size]; } }, watch: { $props: { deep: true, immediate: true, handler() { if (process.env.NODE_ENV === "production") return; if (this.circle && this.link) { vue.warn("You cannot enable circle and link at the same time", this); } this.isInvalidPropCombination(this.circle, this.kind, this.importance); } } }, methods: { buttonClasses() { if (this.link) { return [ "d-link", link_constants.getLinkKindModifier(this.linkKind, this.linkInverted), button_constants.BUTTON_SIZE_MODIFIERS[this.size] ]; } return [ "d-btn", button_constants.BUTTON_IMPORTANCE_MODIFIERS[this.importance], button_constants.BUTTON_KIND_MODIFIERS[this.kind], button_constants.BUTTON_SIZE_MODIFIERS[this.size], { "d-btn--circle": this.circle, "d-btn--loading": this.loading, "d-btn--icon-only": this.isIconOnly(), "d-btn--vertical": this.isVerticalIconLayout(), "d-btn--active": this.active } ]; }, isInvalidPropCombination(circle, kind, importance) { for (const row of button_constants.INVALID_COMBINATION) { if (circle === row.circle && kind === row.kind && importance === row.importance) { console.warn(row.message); return false; } } return true; }, shouldRenderIcon() { return common_utils.hasSlotContent(this.$slots.icon) && !this.link; }, isIconOnly() { return this.shouldRenderIcon() && !common_utils.hasSlotContent(this.$slots.default); }, isVerticalIconLayout() { return !this.isIconOnly() && ["top", "bottom"].includes(this.iconPosition); } } }; const _hoisted_1 = ["type", "disabled", "aria-live", "aria-label"]; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("button", vue.mergeProps({ class: [ "base-button__button", $options.buttonClasses() ], "data-qa": "dt-button", type: $props.type, disabled: $props.disabled, style: { width: $props.width }, "aria-live": $options.computedAriaLive, "aria-label": $props.loading ? "loading" : _ctx.$attrs["aria-label"] }, vue.toHandlers($options.buttonListeners, true)), [ $options.shouldRenderIcon() ? (vue.openBlock(), vue.createElementBlock("span", { key: 0, "data-qa": "dt-button-icon", class: vue.normalizeClass([ "base-button__icon", "d-btn__icon", $data.ICON_POSITION_MODIFIERS[$props.iconPosition] ]) }, [ vue.renderSlot(_ctx.$slots, "icon", { iconSize: $options.iconSize }) ], 2)) : vue.createCommentVNode("", true), $data.hasSlotContent(_ctx.$slots.default) ? (vue.openBlock(), vue.createElementBlock("span", { key: 1, "data-qa": "dt-button-label", class: vue.normalizeClass(["d-btn__label", "base-button__label", $props.labelClass]) }, [ vue.renderSlot(_ctx.$slots, "default") ], 2)) : vue.createCommentVNode("", true) ], 16, _hoisted_1); } const DtButton = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["render", _sfc_render]]); exports.default = DtButton; //# sourceMappingURL=button.vue.cjs.map