UNPKG

@gitlab/ui

Version:
332 lines (318 loc) • 9.87 kB
import uniqueId from 'lodash/uniqueId'; import isBoolean from 'lodash/isBoolean'; import { looseEqual } from '../../../../vendor/bootstrap-vue/src/utils/loose-equal'; import { looseIndexOf } from '../../../../vendor/bootstrap-vue/src/utils/loose-index-of'; import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js'; var script = { name: 'GlFormCheckbox', inject: { getGroup: { // When we remove BFormCheckboxGroup from GlFormCheckboxGroup, we can rename // the `getBvCheckGroup` provide to `getCheckGroup`. from: 'getBvCheckGroup', default: () => () => null } }, inheritAttrs: false, model: { prop: 'checked', event: 'input' }, props: { /** * Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed. */ id: { type: String, required: false, default: undefined }, /** * The current value of the checkbox(es). Must be an array when there are multiple checkboxes bound to the same v-model. */ checked: { type: undefined, required: false, default: null }, /** * When set to `true`, disables the component's functionality and places it in a disabled state. */ disabled: { type: Boolean, required: false, default: false }, /** * Sets the value of the `name` attribute on the form control. */ name: { type: String, required: false, default: undefined }, /** * Adds the `required` attribute to the form control. */ required: { type: Boolean, required: false, default: false }, /** * Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state. */ state: { type: Boolean, required: false, default: null }, /** * Sets the value of `aria-label` attribute on the rendered element. */ ariaLabel: { type: String, required: false, default: undefined }, /** * The ID of the element that provides a label for this component. Used as the value for the `aria-labelledby` attribute. */ ariaLabelledby: { type: String, required: false, default: undefined }, /** * Renders the checkbox in an indeterminate state. Syncable via the .sync modifier. */ indeterminate: { type: Boolean, required: false, default: false }, /** * Value returned when this checkbox is checked. */ value: { type: [Array, Boolean, String], required: false, default: true }, /** * Value returned when this checkbox is unchecked. Note not applicable when multiple checkboxes bound to the same v-model array. */ uncheckedValue: { type: [Array, Boolean, String], required: false, default: false } }, data() { const group = this.getGroup(); return { internalId: this.id ? this.id : uniqueId('gitlab_ui_checkbox_'), localChecked: group ? group.checked : this.checked }; }, computed: { computedLocalChecked: { get() { return this.isGroup ? this.group.localChecked : this.localChecked; }, set(value) { if (this.isGroup) { this.group.localChecked = value; } else { this.localChecked = value; } } }, group() { return this.getGroup(); }, isGroup() { // Is this check a child of check-group? return Boolean(this.group); }, computedState() { if (this.isGroup) return this.group.computedState; return isBoolean(this.state) ? this.state : null; }, stateClass() { if (this.computedState === true) return 'is-valid'; if (this.computedState === false) return 'is-invalid'; return null; }, computedAriaInvalid() { return this.computedState === false ? 'true' : null; }, isChecked() { const { value, computedLocalChecked: checked } = this; return Array.isArray(checked) ? looseIndexOf(checked, value) > -1 : looseEqual(checked, value); }, isDisabled() { // Child can be disabled while parent isn't, but is always disabled if group is return this.isGroup ? this.group.disabled || this.disabled : this.disabled; }, isRequired() { // Required only works when a name is provided for the input(s) // Child can only be required when parent is // Groups will always have a name (either user supplied or auto generated) return this.computedName && (this.isGroup ? this.group.required : this.required); }, computedName() { // Group name preferred over local name return (this.isGroup ? this.group.groupName : this.name) || null; }, computedAttrs() { const { isDisabled: disabled, isRequired: required, value, isChecked: checked } = this; return { ...this.$attrs, id: this.internalId, name: this.computedName, disabled, required, value, checked, 'aria-required': required || null, 'aria-invalid': this.computedAriaInvalid, 'aria-label': this.ariaLabel || null, 'aria-labelledby': this.ariaLabelledby || null }; } }, watch: { checked() { this.checkedWatcher(...arguments); }, indeterminate(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.setIndeterminate(newValue); } }, computedLocalChecked() { this.computedLocalCheckedWatcher(...arguments); } }, mounted() { // Set initial indeterminate state this.setIndeterminate(this.indeterminate); }, methods: { checkedWatcher(newValue) { if (!looseEqual(newValue, this.computedLocalChecked)) { this.computedLocalChecked = newValue; } }, computedLocalCheckedWatcher(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit('input', newValue); const { input } = this.$refs; if (input) { this.$emit('update:indeterminate', input.indeterminate); } } }, handleChange(_ref) { let { target: { checked, indeterminate } } = _ref; const { value, uncheckedValue } = this; // Update `computedLocalChecked` let localChecked = this.computedLocalChecked; if (Array.isArray(localChecked)) { const index = looseIndexOf(localChecked, value); if (checked && index < 0) { // Add value to array localChecked = localChecked.concat(value); } else if (!checked && index > -1) { // Remove value from array localChecked = localChecked.slice(0, index).concat(localChecked.slice(index + 1)); } } else { localChecked = checked ? value : uncheckedValue; } this.computedLocalChecked = localChecked; // Fire events in a `$nextTick()` to ensure the `v-model` is updated this.$nextTick(() => { // Change is only emitted on user interaction this.$emit('change', localChecked); // If this is a child of a group, we emit a change event on it as well if (this.isGroup) { this.group.$emit('change', localChecked); } this.$emit('indeterminate', indeterminate); }); }, setIndeterminate(state) { // Indeterminate only supported in single checkbox mode const computedState = Array.isArray(this.computedLocalChecked) ? false : state; const { input } = this.$refs; if (input) { input.indeterminate = computedState; // Emit update event to prop this.$emit('update:indeterminate', computedState); } }, focus() { if (!this.disabled) { var _this$$refs$input; (_this$$refs$input = this.$refs.input) === null || _this$$refs$input === void 0 ? void 0 : _this$$refs$input.focus(); } }, blur() { if (!this.disabled) { var _this$$refs$input2; (_this$$refs$input2 = this.$refs.input) === null || _this$$refs$input2 === void 0 ? void 0 : _this$$refs$input2.blur(); } } } }; /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-form-checkbox custom-checkbox custom-control"},[_c('input',_vm._b({key:"input",ref:"input",staticClass:"custom-control-input",class:_vm.stateClass,attrs:{"type":"checkbox"},on:{"change":_vm.handleChange}},'input',_vm.computedAttrs,false)),_vm._v(" "),_c('label',{staticClass:"custom-control-label",attrs:{"for":_vm.internalId}},[_vm._t("default"),_vm._v(" "),(Boolean(_vm.$scopedSlots.help))?_c('p',{staticClass:"help-text"},[_vm._t("help")],2):_vm._e()],2)])}; var __vue_staticRenderFns__ = []; /* style */ const __vue_inject_styles__ = undefined; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ const __vue_component__ = /*#__PURE__*/__vue_normalize__( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined ); export { __vue_component__ as default };