UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

236 lines (235 loc) 7.55 kB
import Vue from "vue"; import { LABEL_SIZE_MODIFIERS, DESCRIPTION_SIZE_MODIFIERS } from "../../common/constants.js"; import { SELECT_SIZE_MODIFIERS, SELECT_STATE_MODIFIERS } from "./select_menu_constants.js"; import { getValidationState, getUniqueString } from "../../common/utils.js"; import { MessagesMixin } from "../../common/mixins/input.js"; import { optionsValidator } from "./select_menu_validators.js"; import normalizeComponent from "../../_virtual/_plugin-vue2_normalizer.js"; import DtValidationMessages from "../validation_messages/validation_messages.vue.js"; const _sfc_main = { name: "DtSelectMenu", components: { DtValidationMessages }, mixins: [MessagesMixin], inheritAttrs: false, props: { /** * Label for the select */ label: { type: String, default: "" }, /** * Description for the select */ description: { type: String, default: "" }, /** * Select Menu Options, overridden by default slot. Each option has the following structure: * `{ index: number (optional), value: number || string (required), label: string (required) }` * @param {Object[]} options - Optional - A list that can be used to create a list of select menu options * @param {number} options[].index - Optional - The index of the option * @param {number|string} options[].value - Required - The option value * @param {string} options[].label - Required - The option Label */ options: { type: Array, default: () => [], validator: (options) => optionsValidator(options) }, /** * Sets the selected value of the select menu. If it does not match a value in the options array, then it will be * 'unselected'. */ value: { type: String, default: null }, /** * Controls the size of the select * @values xs, sm, md, lg, xl */ size: { type: String, default: "md", validator: (s) => Object.keys(SELECT_SIZE_MODIFIERS).includes(s) }, /** * Used to customize the label container */ labelClass: { type: [String, Array, Object], default: "" }, /** * Used to customize the description container */ descriptionClass: { type: [String, Array, Object], default: "" }, /** * Used to customize the select */ selectClass: { type: [String, Array, Object], default: "" }, /** * Used to customize each option, should options be provided via prop */ optionClass: { type: [String, Array, Object], default: "" }, /** * A set of props that are passed into the label container */ labelChildProps: { type: Object, default: () => ({}) }, /** * A set of props that are passed into the description container */ descriptionChildProps: { type: Object, default: () => ({}) }, /** * A set of props that are passed into each option, should options be provided via prop */ optionChildProps: { type: Object, default: () => ({}) }, /** * Disabled state of the select * @values true, false */ disabled: { type: Boolean, default: false } }, emits: [ /** * Native input event * * @event input * @type {String | Number} */ "input", /** * Native change event * * @event change * @type {String | Number} */ "change" ], data() { return { LABEL_SIZE_MODIFIERS, DESCRIPTION_SIZE_MODIFIERS, SELECT_SIZE_MODIFIERS, SELECT_STATE_MODIFIERS }; }, computed: { selectListeners() { return { /* TODO Check if any usages of this component leverage $listeners and either remove if unused or scope the removal and migration prior to upgrading to Vue 3.x */ ...this.$listeners, /* * Override input listener to as no-op. Prevents parent input listeners from being passed through onto the input * element which will result in the hander being called twice (once on the select element and once by the * emitted input event by the change listener). */ input: () => { }, change: (event) => this.emitValue(event.target.value, event) }; }, state() { return getValidationState(this.formattedMessages); }, selectKey() { return getUniqueString(); }, descriptionKey() { return `select-${this.selectKey}-description`; }, labelAriaDetails() { if (this.$slots.description || this.description) { return this.descriptionKey; } return this.$attrs["aria-details"]; } }, mounted() { this.validateOptionsPresence(); }, beforeUpdate() { this.validateOptionsPresence(); }, methods: { emitValue(value, event) { this.$emit("input", value, event); this.$emit("change", value, event); }, getOptionKey(value) { return `select-${this.selectKey}-option-${value}`; }, validateOptionsPresence() { var _a; if (((_a = this.options) == null ? void 0 : _a.length) < 1 && !this.$slots.default) { Vue.util.warn("Options are expected to be provided via prop or slot", this); } } } }; var _sfc_render = function render() { var _vm = this, _c = _vm._self._c; return _c("div", [_c("label", [_vm.$slots.label || _vm.label ? _c("div", _vm._b({ class: [ "d-label", _vm.LABEL_SIZE_MODIFIERS[_vm.size], _vm.labelClass ], attrs: { "aria-details": _vm.labelAriaDetails, "data-qa": "dt-select-label" } }, "div", _vm.labelChildProps, false), [_vm._t("label", function() { return [_vm._v(_vm._s(_vm.label))]; })], 2) : _vm._e(), _vm.$slots.description || _vm.description ? _c("div", _vm._b({ class: [ "d-description", _vm.DESCRIPTION_SIZE_MODIFIERS[_vm.size], _vm.descriptionClass ], attrs: { "id": _vm.descriptionKey, "data-qa": "dt-select-description" } }, "div", _vm.descriptionChildProps, false), [_vm._t("description", function() { return [_vm._v(_vm._s(_vm.description))]; })], 2) : _vm._e(), _c("div", { class: [ "d-select", _vm.SELECT_SIZE_MODIFIERS[_vm.size], _vm.selectClass, { "d-select--disabled": _vm.disabled } ], attrs: { "data-qa": "dt-select-wrapper" } }, [_c("select", _vm._g(_vm._b({ ref: "selectElement", class: [ "d-select__input", _vm.SELECT_STATE_MODIFIERS[_vm.state] ], attrs: { "data-qa": "dt-select", "disabled": _vm.disabled }, domProps: { "value": _vm.value } }, "select", _vm.$attrs, false), _vm.selectListeners), [_vm._t("default", function() { return _vm._l(_vm.options, function(option) { return _c("option", _vm._b({ key: _vm.getOptionKey(option.value), class: _vm.optionClass, domProps: { "value": option.value } }, "option", _vm.optionChildProps, false), [_vm._v(" " + _vm._s(option.label) + " ")]); }); })], 2)])]), _c("dt-validation-messages", _vm._b({ class: _vm.messagesClass, attrs: { "validation-messages": _vm.formattedMessages, "show-messages": _vm.showMessages, "data-qa": "dt-select-messages" } }, "dt-validation-messages", _vm.messagesChildProps, false))], 1); }; var _sfc_staticRenderFns = []; var __component__ = /* @__PURE__ */ normalizeComponent( _sfc_main, _sfc_render, _sfc_staticRenderFns ); const select_menu = __component__.exports; export { select_menu as default }; //# sourceMappingURL=select_menu.vue.js.map