@gitlab/ui 128.17.1 → 129.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -93,7 +93,8 @@ var script = {
93
93
  * Value returned when this checkbox is checked.
94
94
  */
95
95
  value: {
96
- type: [Array, Boolean, String],
96
+ // `value` prop can be any type
97
+ type: undefined,
97
98
  required: false,
98
99
  default: true
99
100
  },
@@ -101,7 +102,8 @@ var script = {
101
102
  * Value returned when this checkbox is unchecked. Note not applicable when multiple checkboxes bound to the same v-model array.
102
103
  */
103
104
  uncheckedValue: {
104
- type: [Array, Boolean, String],
105
+ // `uncheckedValue` prop can be any type
106
+ type: undefined,
105
107
  required: false,
106
108
  default: false
107
109
  }
@@ -1,27 +1,225 @@
1
- import { BFormRadio } from '../../../../vendor/bootstrap-vue/src/components/form-radio/form-radio';
1
+ import uniqueId from 'lodash/uniqueId';
2
+ import isBoolean from 'lodash/isBoolean';
3
+ import { looseEqual } from '../../../../vendor/bootstrap-vue/src/utils/loose-equal';
2
4
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
3
5
 
4
- const {
5
- model
6
- } = BFormRadio.options;
7
6
  var script = {
8
7
  name: 'GlFormRadio',
9
- components: {
10
- BFormRadio
8
+ inject: {
9
+ getGroup: {
10
+ // When we remove BFormRadioGroup from GlFormRadioGroup, we can rename
11
+ // the `getBvRadioGroup` provide to `getRadioGroup`.
12
+ from: 'getBvRadioGroup',
13
+ default: () => () => null
14
+ }
11
15
  },
12
16
  inheritAttrs: false,
13
17
  model: {
14
- prop: model.prop,
15
- event: model.event
18
+ prop: 'checked',
19
+ event: 'input'
16
20
  },
17
21
  props: {
18
22
  /**
19
- * Whether the radio is checked
23
+ * Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed.
24
+ */
25
+ id: {
26
+ type: String,
27
+ required: false,
28
+ default: undefined
29
+ },
30
+ /**
31
+ * The current value of the radio. When bound to multiple radios, this is the value of the currently selected radio.
20
32
  */
21
33
  checked: {
22
- type: [String, Number, Boolean, Object],
34
+ // `checked` prop can be any type
35
+ type: undefined,
36
+ required: false,
37
+ default: null
38
+ },
39
+ /**
40
+ * When set to `true`, disables the component's functionality and places it in a disabled state.
41
+ */
42
+ disabled: {
43
+ type: Boolean,
23
44
  required: false,
24
45
  default: false
46
+ },
47
+ /**
48
+ * Sets the value of the `name` attribute on the form control.
49
+ */
50
+ name: {
51
+ type: String,
52
+ required: false,
53
+ default: undefined
54
+ },
55
+ /**
56
+ * Adds the `required` attribute to the form control.
57
+ */
58
+ required: {
59
+ type: Boolean,
60
+ required: false,
61
+ default: false
62
+ },
63
+ /**
64
+ * Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state.
65
+ */
66
+ state: {
67
+ type: Boolean,
68
+ required: false,
69
+ default: null
70
+ },
71
+ /**
72
+ * Value returned when this radio is selected.
73
+ */
74
+ value: {
75
+ // `value` prop can be any type
76
+ type: undefined,
77
+ required: false,
78
+ default: true
79
+ }
80
+ },
81
+ data() {
82
+ const group = this.getGroup();
83
+ return {
84
+ internalId: this.id ? this.id : uniqueId('gitlab_ui_radio_'),
85
+ localChecked: group ? group.checked : this.checked
86
+ };
87
+ },
88
+ computed: {
89
+ computedLocalChecked: {
90
+ get() {
91
+ return this.isGroup ? this.group.localChecked : this.localChecked;
92
+ },
93
+ set(value) {
94
+ if (this.isGroup) {
95
+ this.group.localChecked = value;
96
+ } else {
97
+ this.localChecked = value;
98
+ }
99
+ }
100
+ },
101
+ group() {
102
+ return this.getGroup();
103
+ },
104
+ isGroup() {
105
+ // Is this radio a child of radio-group?
106
+ return Boolean(this.group);
107
+ },
108
+ computedState() {
109
+ if (this.isGroup) return this.group.computedState;
110
+ return isBoolean(this.state) ? this.state : null;
111
+ },
112
+ stateClass() {
113
+ if (this.computedState === true) return 'is-valid';
114
+ if (this.computedState === false) return 'is-invalid';
115
+ return null;
116
+ },
117
+ computedAriaInvalid() {
118
+ return this.computedState === false ? 'true' : null;
119
+ },
120
+ isChecked() {
121
+ return looseEqual(this.computedLocalChecked, this.value);
122
+ },
123
+ isDisabled() {
124
+ // Child can be disabled while parent isn't, but is always disabled if group is
125
+ return this.isGroup ? this.group.disabled || this.disabled : this.disabled;
126
+ },
127
+ isRequired() {
128
+ // Required only works when a name is provided for the input(s)
129
+ // Child can only be required when parent is
130
+ // Groups will always have a name (either user supplied or auto generated)
131
+ return this.computedName && (this.isGroup ? this.group.required : this.required);
132
+ },
133
+ computedName() {
134
+ // Group name preferred over local name
135
+ return (this.isGroup ? this.group.groupName : this.name) || null;
136
+ },
137
+ computedAttrs() {
138
+ const {
139
+ isDisabled: disabled,
140
+ isRequired: required,
141
+ value,
142
+ isChecked: checked
143
+ } = this;
144
+ return {
145
+ ...this.$attrs,
146
+ id: this.internalId,
147
+ name: this.computedName,
148
+ disabled,
149
+ required,
150
+ value,
151
+ checked,
152
+ 'aria-required': required || null,
153
+ 'aria-invalid': this.computedAriaInvalid
154
+ };
155
+ }
156
+ },
157
+ watch: {
158
+ checked() {
159
+ this.checkedWatcher(...arguments);
160
+ },
161
+ computedLocalChecked() {
162
+ this.computedLocalCheckedWatcher(...arguments);
163
+ }
164
+ },
165
+ methods: {
166
+ checkedWatcher(newValue) {
167
+ if (!looseEqual(newValue, this.computedLocalChecked)) {
168
+ this.computedLocalChecked = newValue;
169
+ }
170
+ },
171
+ computedLocalCheckedWatcher(newValue, oldValue) {
172
+ if (!looseEqual(newValue, oldValue)) {
173
+ /**
174
+ * Emitted when the selected value is changed
175
+ *
176
+ * @event input
177
+ * @type {boolean} current selected value of radio group
178
+ */
179
+ this.$emit('input', newValue);
180
+ }
181
+ },
182
+ handleChange() {
183
+ const {
184
+ value
185
+ } = this;
186
+
187
+ // Update `computedLocalChecked`
188
+ this.computedLocalChecked = value;
189
+
190
+ // Fire events in a `$nextTick()` to ensure the `v-model` is updated
191
+ this.$nextTick(() => {
192
+ /**
193
+ * Emitted when the selected value is changed due to user interaction
194
+ *
195
+ * @event change
196
+ * @type {boolean} current selected value of radio group
197
+ */
198
+ this.$emit('change', value);
199
+
200
+ // If this is a child of a group, we emit a change event on it as well
201
+ if (this.isGroup) {
202
+ /**
203
+ * Emitted when the selected value is changed due to user interaction
204
+ *
205
+ * @event change
206
+ * @type {boolean} current selected value of radio group
207
+ */
208
+ this.group.$emit('change', value);
209
+ }
210
+ });
211
+ },
212
+ focus() {
213
+ if (!this.disabled) {
214
+ var _this$$refs$input;
215
+ (_this$$refs$input = this.$refs.input) === null || _this$$refs$input === void 0 ? void 0 : _this$$refs$input.focus();
216
+ }
217
+ },
218
+ blur() {
219
+ if (!this.disabled) {
220
+ var _this$$refs$input2;
221
+ (_this$$refs$input2 = this.$refs.input) === null || _this$$refs$input2 === void 0 ? void 0 : _this$$refs$input2.blur();
222
+ }
25
223
  }
26
224
  }
27
225
  };
@@ -30,7 +228,7 @@ var script = {
30
228
  const __vue_script__ = script;
31
229
 
32
230
  /* template */
33
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-form-radio',_vm._b({staticClass:"gl-form-radio",attrs:{"checked":_vm.checked},on:{"input":function($event){return _vm.$emit('input', $event)},"change":function($event){return _vm.$emit('change', $event)}}},'b-form-radio',_vm.$attrs,false),[_vm._t("default"),_vm._v(" "),(_vm.$scopedSlots.help)?_c('p',{staticClass:"help-text"},[_vm._t("help")],2):_vm._e()],2)};
231
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-form-radio custom-radio custom-control"},[_c('input',_vm._b({key:"input",ref:"input",staticClass:"custom-control-input",class:_vm.stateClass,attrs:{"type":"radio"},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)])};
34
232
  var __vue_staticRenderFns__ = [];
35
233
 
36
234
  /* style */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "128.17.1",
3
+ "version": "129.0.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -93,7 +93,8 @@ export default {
93
93
  * Value returned when this checkbox is checked.
94
94
  */
95
95
  value: {
96
- type: [Array, Boolean, String],
96
+ // `value` prop can be any type
97
+ type: undefined,
97
98
  required: false,
98
99
  default: true,
99
100
  },
@@ -101,7 +102,8 @@ export default {
101
102
  * Value returned when this checkbox is unchecked. Note not applicable when multiple checkboxes bound to the same v-model array.
102
103
  */
103
104
  uncheckedValue: {
104
- type: [Array, Boolean, String],
105
+ // `uncheckedValue` prop can be any type
106
+ type: undefined,
105
107
  required: false,
106
108
  default: false,
107
109
  },
@@ -1,51 +1,240 @@
1
1
  <script>
2
- import { BFormRadio } from '../../../../vendor/bootstrap-vue/src/components/form-radio/form-radio';
3
-
4
- const { model } = BFormRadio.options;
2
+ import uniqueId from 'lodash/uniqueId';
3
+ import isBoolean from 'lodash/isBoolean';
4
+ import { looseEqual } from '../../../../vendor/bootstrap-vue/src/utils/loose-equal';
5
5
 
6
6
  export default {
7
7
  name: 'GlFormRadio',
8
- components: { BFormRadio },
8
+ inject: {
9
+ getGroup: {
10
+ // When we remove BFormRadioGroup from GlFormRadioGroup, we can rename
11
+ // the `getBvRadioGroup` provide to `getRadioGroup`.
12
+ from: 'getBvRadioGroup',
13
+ default: () => () => null,
14
+ },
15
+ },
9
16
  inheritAttrs: false,
10
17
  model: {
11
- prop: model.prop,
12
- event: model.event,
18
+ prop: 'checked',
19
+ event: 'input',
13
20
  },
14
21
  props: {
15
22
  /**
16
- * Whether the radio is checked
23
+ * Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed.
24
+ */
25
+ id: {
26
+ type: String,
27
+ required: false,
28
+ default: undefined,
29
+ },
30
+ /**
31
+ * The current value of the radio. When bound to multiple radios, this is the value of the currently selected radio.
17
32
  */
18
33
  checked: {
19
- type: [String, Number, Boolean, Object],
34
+ // `checked` prop can be any type
35
+ type: undefined,
36
+ required: false,
37
+ default: null,
38
+ },
39
+ /**
40
+ * When set to `true`, disables the component's functionality and places it in a disabled state.
41
+ */
42
+ disabled: {
43
+ type: Boolean,
44
+ required: false,
45
+ default: false,
46
+ },
47
+ /**
48
+ * Sets the value of the `name` attribute on the form control.
49
+ */
50
+ name: {
51
+ type: String,
52
+ required: false,
53
+ default: undefined,
54
+ },
55
+ /**
56
+ * Adds the `required` attribute to the form control.
57
+ */
58
+ required: {
59
+ type: Boolean,
20
60
  required: false,
21
61
  default: false,
22
62
  },
63
+ /**
64
+ * Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state.
65
+ */
66
+ state: {
67
+ type: Boolean,
68
+ required: false,
69
+ default: null,
70
+ },
71
+ /**
72
+ * Value returned when this radio is selected.
73
+ */
74
+ value: {
75
+ // `value` prop can be any type
76
+ type: undefined,
77
+ required: false,
78
+ default: true,
79
+ },
80
+ },
81
+ data() {
82
+ const group = this.getGroup();
83
+ return {
84
+ internalId: this.id ? this.id : uniqueId('gitlab_ui_radio_'),
85
+ localChecked: group ? group.checked : this.checked,
86
+ };
87
+ },
88
+ computed: {
89
+ computedLocalChecked: {
90
+ get() {
91
+ return this.isGroup ? this.group.localChecked : this.localChecked;
92
+ },
93
+ set(value) {
94
+ if (this.isGroup) {
95
+ this.group.localChecked = value;
96
+ } else {
97
+ this.localChecked = value;
98
+ }
99
+ },
100
+ },
101
+ group() {
102
+ return this.getGroup();
103
+ },
104
+ isGroup() {
105
+ // Is this radio a child of radio-group?
106
+ return Boolean(this.group);
107
+ },
108
+ computedState() {
109
+ if (this.isGroup) return this.group.computedState;
110
+ return isBoolean(this.state) ? this.state : null;
111
+ },
112
+ stateClass() {
113
+ if (this.computedState === true) return 'is-valid';
114
+ if (this.computedState === false) return 'is-invalid';
115
+ return null;
116
+ },
117
+ computedAriaInvalid() {
118
+ return this.computedState === false ? 'true' : null;
119
+ },
120
+ isChecked() {
121
+ return looseEqual(this.computedLocalChecked, this.value);
122
+ },
123
+ isDisabled() {
124
+ // Child can be disabled while parent isn't, but is always disabled if group is
125
+ return this.isGroup ? this.group.disabled || this.disabled : this.disabled;
126
+ },
127
+ isRequired() {
128
+ // Required only works when a name is provided for the input(s)
129
+ // Child can only be required when parent is
130
+ // Groups will always have a name (either user supplied or auto generated)
131
+ return this.computedName && (this.isGroup ? this.group.required : this.required);
132
+ },
133
+ computedName() {
134
+ // Group name preferred over local name
135
+ return (this.isGroup ? this.group.groupName : this.name) || null;
136
+ },
137
+ computedAttrs() {
138
+ const { isDisabled: disabled, isRequired: required, value, isChecked: checked } = this;
139
+
140
+ return {
141
+ ...this.$attrs,
142
+ id: this.internalId,
143
+ name: this.computedName,
144
+ disabled,
145
+ required,
146
+ value,
147
+ checked,
148
+ 'aria-required': required || null,
149
+ 'aria-invalid': this.computedAriaInvalid,
150
+ };
151
+ },
152
+ },
153
+ watch: {
154
+ checked(...args) {
155
+ this.checkedWatcher(...args);
156
+ },
157
+ computedLocalChecked(...args) {
158
+ this.computedLocalCheckedWatcher(...args);
159
+ },
160
+ },
161
+ methods: {
162
+ checkedWatcher(newValue) {
163
+ if (!looseEqual(newValue, this.computedLocalChecked)) {
164
+ this.computedLocalChecked = newValue;
165
+ }
166
+ },
167
+ computedLocalCheckedWatcher(newValue, oldValue) {
168
+ if (!looseEqual(newValue, oldValue)) {
169
+ /**
170
+ * Emitted when the selected value is changed
171
+ *
172
+ * @event input
173
+ * @type {boolean} current selected value of radio group
174
+ */
175
+ this.$emit('input', newValue);
176
+ }
177
+ },
178
+ handleChange() {
179
+ const { value } = this;
180
+
181
+ // Update `computedLocalChecked`
182
+ this.computedLocalChecked = value;
183
+
184
+ // Fire events in a `$nextTick()` to ensure the `v-model` is updated
185
+ this.$nextTick(() => {
186
+ /**
187
+ * Emitted when the selected value is changed due to user interaction
188
+ *
189
+ * @event change
190
+ * @type {boolean} current selected value of radio group
191
+ */
192
+ this.$emit('change', value);
193
+
194
+ // If this is a child of a group, we emit a change event on it as well
195
+ if (this.isGroup) {
196
+ /**
197
+ * Emitted when the selected value is changed due to user interaction
198
+ *
199
+ * @event change
200
+ * @type {boolean} current selected value of radio group
201
+ */
202
+ this.group.$emit('change', value);
203
+ }
204
+ });
205
+ },
206
+ focus() {
207
+ if (!this.disabled) {
208
+ this.$refs.input?.focus();
209
+ }
210
+ },
211
+ blur() {
212
+ if (!this.disabled) {
213
+ this.$refs.input?.blur();
214
+ }
215
+ },
23
216
  },
24
217
  };
25
218
  </script>
26
219
 
27
220
  <template>
28
- <!--
29
- Emitted when the selected value is changed
30
- @event input
31
- @type {boolean} current selected value of radio group
32
-
33
- Emitted when the selected value is changed due to user interaction
34
- @event change
35
- @type {boolean} current selected value of radio group
36
- -->
37
- <b-form-radio
38
- class="gl-form-radio"
39
- :checked="checked"
40
- v-bind="$attrs"
41
- @input="$emit('input', $event)"
42
- @change="$emit('change', $event)"
43
- >
44
- <!-- @slot Content to use for the label -->
45
- <slot></slot>
46
- <p v-if="$scopedSlots.help" class="help-text">
47
- <!-- @slot Content provided here will be shown beneath the radio. Typically used for help or descriptive text. -->
48
- <slot name="help"></slot>
49
- </p>
50
- </b-form-radio>
221
+ <div class="gl-form-radio custom-radio custom-control">
222
+ <input
223
+ ref="input"
224
+ key="input"
225
+ v-bind="computedAttrs"
226
+ type="radio"
227
+ class="custom-control-input"
228
+ :class="stateClass"
229
+ @change="handleChange"
230
+ />
231
+ <label :for="internalId" class="custom-control-label">
232
+ <!-- @slot Content to use for the label -->
233
+ <slot></slot>
234
+ <p v-if="Boolean($scopedSlots.help)" class="help-text">
235
+ <!-- @slot Content provided here will be shown beneath the radio. Typically used for help or descriptive text. -->
236
+ <slot name="help"></slot>
237
+ </p>
238
+ </label>
239
+ </div>
51
240
  </template>