@gitlab/ui
Version:
GitLab UI Components
332 lines (318 loc) • 9.87 kB
JavaScript
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 };