@sandlada/vue-mdc
Version:

229 lines (228 loc) • 7.22 kB
JavaScript
/**
* @license
* Copyright 2025 Sandlada & Kai Orion
* SPDX-License-Identifier: MIT
*/
import { defineComponent, ref, computed, toRef, onMounted, onBeforeUnmount, createVNode } from "vue";
import { useReflectAttribute } from "../../node_modules/@glare-labs/vue-reflect-attribute/build/vue-reflect-attribute.js";
import { componentNamePrefix } from "../../internals/component-name-prefix/component-name-prefix.js";
import { isServer } from "../../utils/is-server.js";
import { useObserveProps } from "../../utils/observe-props.js";
import { Elevation } from "../elevation/elevation.js";
import { FocusRing } from "../focus-ring/focus-ring.js";
import "../../internals/navigation/render-navigation-destination.js";
import { Ripple } from "../ripple/ripple.js";
import { props, ButtonAppearance } from "./button.definition.js";
import css from "./styles/button.module.scss.js";
const Button = /* @__PURE__ */ defineComponent({
name: `${componentNamePrefix}-button`,
slots: {},
props,
setup(props2, {
slots
}) {
const root = ref(null);
const _selected = ref(props2.defaultSelected);
const selected = computed({
get: () => _selected.value,
set: (value) => {
_selected.value = value;
}
});
const _appearance = ref(props2.appearance);
const _size = ref(props2.size);
const _shape = ref(props2.shape);
const _togglable = ref(props2.togglable);
const _defaultSelected = ref(props2.defaultSelected);
const _disabled = ref(props2.disabled);
const _type = ref(props2.type);
const _href = ref(props2.href);
const _target = ref(props2.target);
const _form = ref(props2.form);
const _name = ref(props2.name);
const _value = ref(props2.value);
useReflectAttribute(root, {
attributes: [{
attribute: "appearance",
ref: _appearance,
reflect: true,
type: "string"
}, {
attribute: "size",
ref: _size,
reflect: true,
type: "string"
}, {
attribute: "shape",
ref: _shape,
reflect: true,
type: "string"
}, {
attribute: "togglable",
ref: _togglable,
reflect: true,
type: "boolean"
}, {
attribute: "default-selected",
ref: _defaultSelected,
reflect: true,
type: "boolean"
}, {
attribute: "disabled",
ref: _disabled,
reflect: true,
type: "boolean"
}, {
attribute: "type",
ref: _type,
reflect: true,
type: "string"
}, {
attribute: "href",
ref: _href,
reflect: true,
type: "string"
}, {
attribute: "target",
ref: _target,
reflect: true,
type: "string"
}, {
attribute: "form",
ref: _form,
reflect: true,
type: "string"
}, {
attribute: "name",
ref: _name,
reflect: true,
type: "string"
}, {
attribute: "value",
ref: _value,
reflect: true,
type: "string"
}],
onAttributeChange: (attr, oldValue, newValue) => {
}
});
useObserveProps([{
id: "size",
property: toRef(props2, "size"),
callback: (value) => {
_size.value = value;
}
}, {
id: "appearance",
property: toRef(props2, "appearance"),
callback: (value) => {
_appearance.value = value;
}
}, {
id: "size",
property: toRef(props2, "size"),
callback: (value) => {
_size.value = value;
}
}, {
id: "shape",
property: toRef(props2, "shape"),
callback: (value) => {
_shape.value = value;
}
}, {
id: "togglable",
property: toRef(props2, "togglable"),
callback: (value) => {
_togglable.value = value;
}
}, {
id: "disabled",
property: toRef(props2, "disabled"),
callback: (value) => {
_disabled.value = value;
}
}, {
id: "type",
property: toRef(props2, "type"),
callback: (value) => {
_type.value = value;
}
}, {
id: "href",
property: toRef(props2, "href"),
callback: (value) => {
_href.value = value;
}
}]);
const handleClick = async (e) => {
if (_href.value && _disabled.value) {
e.stopImmediatePropagation();
e.preventDefault();
return;
}
selected.value = !selected.value;
};
onMounted(() => {
if (isServer()) {
return;
}
root.value?.addEventListener("click", handleClick);
});
onBeforeUnmount(() => {
root.value?.removeEventListener("click", handleClick);
});
return () => {
const elevationButtonArray = [ButtonAppearance.Elevated, ButtonAppearance.Filled, ButtonAppearance.FilledTonal];
const needElevation = elevationButtonArray.includes(_appearance.value);
const needOutline = _appearance.value === ButtonAppearance.Outlined;
const iconState = slots["leading-icon"] ? css.left : slots["trailing-icon"] ? css.right : null;
const isLink = _href.value !== null;
const isTogglable = _appearance.value !== "text" && _togglable.value;
const className = [css[_appearance.value], iconState, _disabled.value && css.disabled, css[_size.value], css[_shape.value], isTogglable && css.togglable, isTogglable && (selected.value ? css.selected : css.unselected)];
const renderContent = createVNode("span", {
"class": css.button
}, [createVNode("span", {
"class": css.touch
}, null), slots["leading-icon"] && slots["leading-icon"](), createVNode("span", {
"class": [css.label]
}, [slots.default && slots.default()]), slots["trailing-icon"] && slots["trailing-icon"]()]);
const renderButtonWrapper = createVNode("button", {
"data-component": "button",
"class": className,
"role": "button",
"ref": root,
"tabindex": _disabled.value ? -1 : 0
}, [createVNode(Ripple, null, null), createVNode(FocusRing, {
"shapeInherit": false
}, null), needElevation && createVNode(Elevation, null, null), needOutline && createVNode("div", {
"aria-hidden": "true",
"class": [css.outline]
}, null), createVNode("div", {
"aria-hidden": "true",
"class": [css.background]
}, null), renderContent]);
const renderLinkWrapper = createVNode("a", {
"data-component": "button",
"class": className,
"role": "button",
"ref": root,
"tabindex": _disabled.value ? -1 : 0
}, [createVNode(Ripple, null, null), createVNode(FocusRing, {
"shapeInherit": false
}, null), needElevation && createVNode(Elevation, null, null), needOutline && createVNode("div", {
"aria-hidden": "true",
"class": [css.outline]
}, null), createVNode("div", {
"aria-hidden": "true",
"class": [css.background]
}, null), renderContent]);
return isLink ? renderLinkWrapper : renderButtonWrapper;
};
},
inheritAttrs: true
});
export {
Button
};
//# sourceMappingURL=button.js.map