@gitlab/ui 138.0.0 → 138.2.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.
- package/README.md +3 -12
- package/dist/components/base/filtered_search/filtered_search_suggestion_list.js +1 -1
- package/dist/components/base/form/form_select/form_select.js +322 -6
- package/dist/components/base/sorting/sorting.js +27 -5
- package/dist/components/base/toggle/toggle.js +24 -1
- package/dist/components/charts/chart/chart.js +22 -0
- package/dist/config.js +14 -2
- package/dist/vendor/bootstrap-vue/src/constants/components.js +1 -4
- package/package.json +3 -11
- package/src/components/base/filtered_search/filtered_search_suggestion_list.vue +2 -1
- package/src/components/base/form/form_select/form_select.vue +389 -9
- package/src/components/base/sorting/sorting.vue +29 -4
- package/src/components/base/toggle/toggle.vue +25 -2
- package/src/components/charts/chart/chart.vue +18 -0
- package/src/config.js +16 -1
- package/src/vendor/bootstrap-vue/src/constants/components.js +0 -3
- package/translations.js +2 -2
- package/dist/vendor/bootstrap-vue/src/components/form-select/form-select-option-group.js +0 -51
- package/dist/vendor/bootstrap-vue/src/components/form-select/form-select-option.js +0 -41
- package/dist/vendor/bootstrap-vue/src/components/form-select/form-select.js +0 -153
- package/dist/vendor/bootstrap-vue/src/components/form-select/helpers/mixin-options.js +0 -63
- package/dist/vendor/bootstrap-vue/src/components/form-select/index.js +0 -3
- package/src/vendor/bootstrap-vue/src/components/form-select/form-select-option-group.js +0 -46
- package/src/vendor/bootstrap-vue/src/components/form-select/form-select-option.js +0 -35
- package/src/vendor/bootstrap-vue/src/components/form-select/form-select.js +0 -156
- package/src/vendor/bootstrap-vue/src/components/form-select/helpers/mixin-options.js +0 -60
- package/src/vendor/bootstrap-vue/src/components/form-select/index.js +0 -5
package/README.md
CHANGED
|
@@ -48,20 +48,11 @@ See <https://design.gitlab.com/storybook> for documentation.
|
|
|
48
48
|
[GitPod](https://www.gitpod.io/docs/configure/authentication/gitlab) can be used to set up a
|
|
49
49
|
UNIX-like environment in which to build it.
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
Complete the [project setup](../../README.md#project-setup) in the repository root README, then
|
|
52
|
+
build and launch Storybook:
|
|
53
53
|
|
|
54
54
|
```sh
|
|
55
|
-
|
|
56
|
-
git clone git@gitlab.com:gitlab-org/gitlab-services/design.gitlab.com.git
|
|
57
|
-
|
|
58
|
-
# Navigate to the root of the project
|
|
59
|
-
cd design.gitlab.com/packages/gitlab-ui
|
|
60
|
-
|
|
61
|
-
# Install all the dependencies of the project
|
|
62
|
-
yarn # or yarn install
|
|
63
|
-
|
|
64
|
-
# Build and launch storybook to see the components in the browser
|
|
55
|
+
cd packages/gitlab-ui
|
|
65
56
|
yarn storybook
|
|
66
57
|
```
|
|
67
58
|
|
|
@@ -104,7 +104,7 @@ var script = {
|
|
|
104
104
|
const __vue_script__ = script;
|
|
105
105
|
|
|
106
106
|
/* template */
|
|
107
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',{class:_vm.listClasses},[_c('li',{ref:"top"}),_vm._v(" "),_vm._t("default")],2)};
|
|
107
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',{class:_vm.listClasses},[_c('li',{ref:"top",attrs:{"aria-hidden":"true","role":"presentation"}}),_vm._v(" "),_vm._t("default")],2)};
|
|
108
108
|
var __vue_staticRenderFns__ = [];
|
|
109
109
|
|
|
110
110
|
/* style */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { isObject } from 'lodash-es';
|
|
2
|
-
import { BFormSelect } from '../../../../vendor/bootstrap-vue/src/components/form-select/form-select';
|
|
1
|
+
import { isObject, isBoolean, uniqueId, isPlainObject, get, isNull, isUndefined } from 'lodash-es';
|
|
3
2
|
import { formInputWidths } from '../../../../utils/constants';
|
|
3
|
+
import { isVisible } from '../../../../utils/utils';
|
|
4
|
+
import { SafeHtmlDirective } from '../../../../directives/safe_html/safe_html';
|
|
4
5
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
5
6
|
|
|
6
7
|
function _arrayLikeToArray(r, a) {
|
|
@@ -75,13 +76,180 @@ function _unsupportedIterableToArray(r, a) {
|
|
|
75
76
|
const _excluded = ["default"];
|
|
76
77
|
var script = {
|
|
77
78
|
name: 'GlFormSelect',
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
directives: {
|
|
80
|
+
SafeHtml: SafeHtmlDirective
|
|
80
81
|
},
|
|
81
82
|
inheritAttrs: false,
|
|
82
83
|
props: {
|
|
83
84
|
/**
|
|
84
|
-
*
|
|
85
|
+
* Current value of the select. Should be set to an array when the 'multiple' prop is set
|
|
86
|
+
*/
|
|
87
|
+
value: {
|
|
88
|
+
// Value can be any type!
|
|
89
|
+
type: undefined,
|
|
90
|
+
required: false,
|
|
91
|
+
default: undefined
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Array of items to render in the component
|
|
95
|
+
*/
|
|
96
|
+
options: {
|
|
97
|
+
type: [Array, Object],
|
|
98
|
+
required: false,
|
|
99
|
+
default: undefined
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* When set to a number larger than 0, will set the number of display option rows. Note not all browser will respect this setting
|
|
103
|
+
* @deprecated Only useful with `multiple`, which is also deprecated.
|
|
104
|
+
*/
|
|
105
|
+
selectSize: {
|
|
106
|
+
type: Number,
|
|
107
|
+
required: false,
|
|
108
|
+
default: 0
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed
|
|
112
|
+
*/
|
|
113
|
+
id: {
|
|
114
|
+
type: String,
|
|
115
|
+
required: false,
|
|
116
|
+
default: undefined
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Render the form control in plain mode, rather than custom styled mode
|
|
120
|
+
* @deprecated Use a native <select> element instead.
|
|
121
|
+
*/
|
|
122
|
+
plain: {
|
|
123
|
+
type: Boolean,
|
|
124
|
+
required: false,
|
|
125
|
+
default: false
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Set the size of the component's appearance. 'sm', 'md' (default), or 'lg'
|
|
129
|
+
* @deprecated Has no effect. Use the `width` prop instead.
|
|
130
|
+
*/
|
|
131
|
+
size: {
|
|
132
|
+
type: String,
|
|
133
|
+
required: false,
|
|
134
|
+
default: undefined
|
|
135
|
+
},
|
|
136
|
+
/**
|
|
137
|
+
* Optional value to set for the 'aria-invalid' attribute. Supported values are 'true' and 'false'. If not set, the 'state' prop will dictate the value
|
|
138
|
+
*/
|
|
139
|
+
ariaInvalid: {
|
|
140
|
+
type: [Boolean, String],
|
|
141
|
+
required: false,
|
|
142
|
+
default: false
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state
|
|
146
|
+
*/
|
|
147
|
+
state: {
|
|
148
|
+
// Tri-state prop: true, false, null (or undefined)
|
|
149
|
+
type: Boolean,
|
|
150
|
+
required: false,
|
|
151
|
+
default: null
|
|
152
|
+
},
|
|
153
|
+
/**
|
|
154
|
+
* Field name in the `options` array that should be used for the value
|
|
155
|
+
*/
|
|
156
|
+
valueField: {
|
|
157
|
+
type: String,
|
|
158
|
+
required: false,
|
|
159
|
+
default: 'value'
|
|
160
|
+
},
|
|
161
|
+
/**
|
|
162
|
+
* The key to use from the option object to get the label
|
|
163
|
+
*/
|
|
164
|
+
labelField: {
|
|
165
|
+
type: String,
|
|
166
|
+
required: false,
|
|
167
|
+
default: 'label'
|
|
168
|
+
},
|
|
169
|
+
/**
|
|
170
|
+
* The key to use from the option object to get the options
|
|
171
|
+
*/
|
|
172
|
+
optionsField: {
|
|
173
|
+
type: String,
|
|
174
|
+
required: false,
|
|
175
|
+
default: 'options'
|
|
176
|
+
},
|
|
177
|
+
/**
|
|
178
|
+
* Field name in the `options` array that should be used for the text label
|
|
179
|
+
*/
|
|
180
|
+
textField: {
|
|
181
|
+
type: String,
|
|
182
|
+
required: false,
|
|
183
|
+
default: 'text'
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Field name in the `options` array that should be used for the disabled state
|
|
187
|
+
*/
|
|
188
|
+
disabledField: {
|
|
189
|
+
type: String,
|
|
190
|
+
required: false,
|
|
191
|
+
default: 'disabled'
|
|
192
|
+
},
|
|
193
|
+
/**
|
|
194
|
+
* Field name in the `options` array that should be used for the html label instead of text field
|
|
195
|
+
* @deprecated Using the `.html` field (whatever its name) is potentially unsafe.
|
|
196
|
+
*/
|
|
197
|
+
htmlField: {
|
|
198
|
+
type: String,
|
|
199
|
+
required: false,
|
|
200
|
+
default: 'html'
|
|
201
|
+
},
|
|
202
|
+
/**
|
|
203
|
+
* When set, allows multiple options to be selected (multi-select)
|
|
204
|
+
* @deprecated Use GlCollapsibleListbox instead.
|
|
205
|
+
*/
|
|
206
|
+
multiple: {
|
|
207
|
+
type: Boolean,
|
|
208
|
+
required: false,
|
|
209
|
+
default: false
|
|
210
|
+
},
|
|
211
|
+
/**
|
|
212
|
+
* When set to `true`, attempts to auto-focus the control when it is mounted, or re-activated when in a keep-alive. Does not set the `autofocus` attribute on the control
|
|
213
|
+
*/
|
|
214
|
+
autofocus: {
|
|
215
|
+
type: Boolean,
|
|
216
|
+
required: false,
|
|
217
|
+
default: false
|
|
218
|
+
},
|
|
219
|
+
/**
|
|
220
|
+
* When set to `true`, disables the component's functionality and places it in a disabled state
|
|
221
|
+
*/
|
|
222
|
+
disabled: {
|
|
223
|
+
type: Boolean,
|
|
224
|
+
required: false,
|
|
225
|
+
default: false
|
|
226
|
+
},
|
|
227
|
+
/**
|
|
228
|
+
* ID of the form that the form control belongs to. Sets the `form` attribute on the control
|
|
229
|
+
*/
|
|
230
|
+
form: {
|
|
231
|
+
type: String,
|
|
232
|
+
required: false,
|
|
233
|
+
default: undefined
|
|
234
|
+
},
|
|
235
|
+
/**
|
|
236
|
+
* Sets the value of the `name` attribute on the form control
|
|
237
|
+
*/
|
|
238
|
+
name: {
|
|
239
|
+
type: String,
|
|
240
|
+
required: false,
|
|
241
|
+
default: undefined
|
|
242
|
+
},
|
|
243
|
+
/**
|
|
244
|
+
* Adds the `required` attribute to the form control
|
|
245
|
+
*/
|
|
246
|
+
required: {
|
|
247
|
+
type: Boolean,
|
|
248
|
+
required: false,
|
|
249
|
+
default: false
|
|
250
|
+
},
|
|
251
|
+
/**
|
|
252
|
+
* Maximum width of the Select
|
|
85
253
|
*/
|
|
86
254
|
width: {
|
|
87
255
|
type: [String, Object],
|
|
@@ -101,7 +269,32 @@ var script = {
|
|
|
101
269
|
default: ''
|
|
102
270
|
}
|
|
103
271
|
},
|
|
272
|
+
data() {
|
|
273
|
+
return {
|
|
274
|
+
localValue: this.value,
|
|
275
|
+
localId: null
|
|
276
|
+
};
|
|
277
|
+
},
|
|
104
278
|
computed: {
|
|
279
|
+
computedId() {
|
|
280
|
+
return this.id || this.localId;
|
|
281
|
+
},
|
|
282
|
+
computedSelectSize() {
|
|
283
|
+
// Custom selects with a size of zero causes the arrows to be hidden,
|
|
284
|
+
// so dont render the size attribute in this case
|
|
285
|
+
return !this.plain && this.selectSize === 0 ? null : this.selectSize;
|
|
286
|
+
},
|
|
287
|
+
computedAriaInvalid() {
|
|
288
|
+
const ariaInvalid = this.ariaInvalid;
|
|
289
|
+
if (ariaInvalid === true || ariaInvalid === 'true' || ariaInvalid === '') {
|
|
290
|
+
return 'true';
|
|
291
|
+
}
|
|
292
|
+
return this.computedState === false ? 'true' : ariaInvalid;
|
|
293
|
+
},
|
|
294
|
+
computedState() {
|
|
295
|
+
// If not a boolean, ensure that value is null
|
|
296
|
+
return isBoolean(this.state) ? this.state : null;
|
|
297
|
+
},
|
|
105
298
|
cssClasses() {
|
|
106
299
|
if (this.width === null) {
|
|
107
300
|
return [];
|
|
@@ -124,6 +317,129 @@ var script = {
|
|
|
124
317
|
|
|
125
318
|
// eslint-disable-next-line @gitlab/tailwind-no-interpolation -- Not a CSS utility
|
|
126
319
|
return [`gl-form-select-${this.width}`];
|
|
320
|
+
},
|
|
321
|
+
stateClass() {
|
|
322
|
+
if (this.computedState === true) return 'is-valid';
|
|
323
|
+
if (this.computedState === false) return 'is-invalid';
|
|
324
|
+
return null;
|
|
325
|
+
},
|
|
326
|
+
inputClass() {
|
|
327
|
+
return ['gl-form-select', this.plain ? 'form-control' : 'custom-select', this.size && this.plain ? `form-control-${this.size}` : null, this.size && !this.plain ? `custom-select-${this.size}` : null, this.stateClass, this.selectClass];
|
|
328
|
+
},
|
|
329
|
+
normalizedOptions() {
|
|
330
|
+
return this.normalizeOptions(this.options);
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
watch: {
|
|
334
|
+
value(newValue) {
|
|
335
|
+
this.localValue = newValue;
|
|
336
|
+
},
|
|
337
|
+
localValue(newValue) {
|
|
338
|
+
/**
|
|
339
|
+
* Emitted when the select value changes
|
|
340
|
+
*
|
|
341
|
+
* @event input
|
|
342
|
+
* @type {any}
|
|
343
|
+
*/
|
|
344
|
+
this.$emit('input', newValue);
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
activated() {
|
|
348
|
+
this.handleAutofocus();
|
|
349
|
+
},
|
|
350
|
+
async mounted() {
|
|
351
|
+
this.handleAutofocus();
|
|
352
|
+
await this.$nextTick();
|
|
353
|
+
// Update DOM with auto-generated ID after mount
|
|
354
|
+
// to prevent SSR hydration errors
|
|
355
|
+
this.localId = uniqueId('gl-form-select-');
|
|
356
|
+
},
|
|
357
|
+
methods: {
|
|
358
|
+
focus() {
|
|
359
|
+
var _this$$refs$select;
|
|
360
|
+
(_this$$refs$select = this.$refs.select) === null || _this$$refs$select === void 0 ? void 0 : _this$$refs$select.focus();
|
|
361
|
+
},
|
|
362
|
+
blur() {
|
|
363
|
+
var _this$$refs$select2;
|
|
364
|
+
(_this$$refs$select2 = this.$refs.select) === null || _this$$refs$select2 === void 0 ? void 0 : _this$$refs$select2.blur();
|
|
365
|
+
},
|
|
366
|
+
normalizeOptions(options) {
|
|
367
|
+
// Normalize the given options array
|
|
368
|
+
if (Array.isArray(options)) return options.map(option => this.normalizeOption(option));
|
|
369
|
+
if (isPlainObject(options)) {
|
|
370
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
371
|
+
// Deprecate the object options format
|
|
372
|
+
// eslint-disable-next-line no-console
|
|
373
|
+
console.warn('[@gitlab/ui] GlFormSelect - Setting prop "options" to an object is deprecated. Use the array format instead.');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Normalize a `options` object to an array of options
|
|
377
|
+
return Object.keys(options).map(key => this.normalizeOption(options[key] || {}, key));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// If not an array or object, return an empty array
|
|
381
|
+
return [];
|
|
382
|
+
},
|
|
383
|
+
normalizeOption(option) {
|
|
384
|
+
let key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
385
|
+
// When the option is an object, normalize it
|
|
386
|
+
if (isPlainObject(option)) {
|
|
387
|
+
const value = get(option, this.valueField);
|
|
388
|
+
const text = get(option, this.textField);
|
|
389
|
+
const options = get(option, this.optionsField, null);
|
|
390
|
+
// When it has options, create an <optgroup> object
|
|
391
|
+
if (!isNull(options)) {
|
|
392
|
+
return {
|
|
393
|
+
label: String(get(option, this.labelField) || text),
|
|
394
|
+
options: this.normalizeOptions(options)
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
// Otherwise create an <option> object
|
|
398
|
+
return {
|
|
399
|
+
value: isUndefined(value) ? key || text : value,
|
|
400
|
+
text: String(isUndefined(text) ? key : text),
|
|
401
|
+
html: get(option, this.htmlField),
|
|
402
|
+
disabled: Boolean(get(option, this.disabledField))
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
// Otherwise create an <option> object from the given value
|
|
406
|
+
return {
|
|
407
|
+
value: key || option,
|
|
408
|
+
text: String(option),
|
|
409
|
+
disabled: false
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
isOptionGroup(option) {
|
|
413
|
+
return Array.isArray(option.options);
|
|
414
|
+
},
|
|
415
|
+
async onChange(event) {
|
|
416
|
+
const target = event.target;
|
|
417
|
+
const selectedValue = Array.from(target.options).filter(option => option.selected)
|
|
418
|
+
// NOTE: the _value property is set up by both Vue 2 and 3 explicitly for the
|
|
419
|
+
// purpose of handling non-string values on form elements.
|
|
420
|
+
//
|
|
421
|
+
// See:
|
|
422
|
+
// - https://github.com/vuejs/vue/blob/v2.7.16/src/platforms/web/runtime/modules/dom-props.ts#L42-L44
|
|
423
|
+
// - https://github.com/vuejs/vue/blob/v2.7.16/test/unit/modules/vdom/modules/dom-props.spec.ts#L38
|
|
424
|
+
// - https://github.com/vuejs/core/blob/v3.4.27/packages/runtime-dom/src/modules/props.ts#L48-L50
|
|
425
|
+
// - https://github.com/vuejs/core/blob/v3.4.27/packages/runtime-dom/__tests__/patchProps.spec.ts#L25
|
|
426
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
427
|
+
.map(option => '_value' in option ? option._value : option.value);
|
|
428
|
+
this.localValue = target.multiple ? selectedValue : selectedValue[0];
|
|
429
|
+
await this.$nextTick();
|
|
430
|
+
/**
|
|
431
|
+
* Emitted when the select value changes via user interaction
|
|
432
|
+
*
|
|
433
|
+
* @event change
|
|
434
|
+
* @type {any}
|
|
435
|
+
*/
|
|
436
|
+
this.$emit('change', this.localValue);
|
|
437
|
+
},
|
|
438
|
+
async handleAutofocus() {
|
|
439
|
+
await this.$nextTick();
|
|
440
|
+
window.requestAnimationFrame(() => {
|
|
441
|
+
if (this.autofocus && isVisible(this.$refs.select)) this.focus();
|
|
442
|
+
});
|
|
127
443
|
}
|
|
128
444
|
}
|
|
129
445
|
};
|
|
@@ -132,7 +448,7 @@ var script = {
|
|
|
132
448
|
const __vue_script__ = script;
|
|
133
449
|
|
|
134
450
|
/* template */
|
|
135
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('span',{staticClass:"gl-form-select-wrapper",class:_vm.cssClasses},[_c('
|
|
451
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('span',{staticClass:"gl-form-select-wrapper",class:_vm.cssClasses},[_c('select',_vm._b({directives:[{name:"model",rawName:"v-model",value:(_vm.localValue),expression:"localValue"}],ref:"select",class:_vm.inputClass,attrs:{"id":_vm.computedId,"aria-invalid":_vm.computedAriaInvalid,"aria-required":_vm.required ? 'true' : null,"disabled":_vm.disabled,"form":_vm.form,"multiple":_vm.multiple,"name":_vm.name,"required":_vm.required,"size":_vm.computedSelectSize},on:{"change":[function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return val}); _vm.localValue=$event.target.multiple ? $$selectedVal : $$selectedVal[0];},_vm.onChange]}},'select',_vm.$attrs,false),[_vm._t("first"),_vm._v(" "),_vm._l((_vm.normalizedOptions),function(option,index){return [(_vm.isOptionGroup(option))?[_c('optgroup',{key:index,attrs:{"label":option.label}},[_vm._l((option.options),function(childOption,childIndex){return [(childOption.html)?_c('option',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(childOption.html),expression:"childOption.html"}],key:(childIndex + "-html"),attrs:{"disabled":childOption.disabled},domProps:{"value":childOption.value}}):_c('option',{key:childIndex,attrs:{"disabled":childOption.disabled},domProps:{"value":childOption.value}},[_vm._v("\n "+_vm._s(childOption.text)+"\n ")])]})],2)]:[(option.html)?_c('option',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(option.html),expression:"option.html"}],key:(index + "-html"),attrs:{"disabled":option.disabled},domProps:{"value":option.value}}):_c('option',{key:index,attrs:{"disabled":option.disabled},domProps:{"value":option.value}},[_vm._v("\n "+_vm._s(option.text)+"\n ")])]]}),_vm._v(" "),_vm._t("default")],2)])};
|
|
136
452
|
var __vue_staticRenderFns__ = [];
|
|
137
453
|
|
|
138
454
|
/* style */
|
|
@@ -97,6 +97,15 @@ var script = {
|
|
|
97
97
|
type: Boolean,
|
|
98
98
|
required: false,
|
|
99
99
|
default: true
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Disables the entire sorting control (both the sort-by dropdown and the
|
|
103
|
+
* sort direction toggle) while keeping it visible.
|
|
104
|
+
*/
|
|
105
|
+
disabled: {
|
|
106
|
+
type: Boolean,
|
|
107
|
+
required: false,
|
|
108
|
+
default: false
|
|
100
109
|
}
|
|
101
110
|
},
|
|
102
111
|
data() {
|
|
@@ -106,7 +115,13 @@ var script = {
|
|
|
106
115
|
};
|
|
107
116
|
},
|
|
108
117
|
computed: {
|
|
118
|
+
unavailableLabel() {
|
|
119
|
+
return translate('GlSorting.sortingUnavailable', 'Sorting is unavailable');
|
|
120
|
+
},
|
|
109
121
|
sortingListboxLabel() {
|
|
122
|
+
if (this.disabled) {
|
|
123
|
+
return this.unavailableLabel;
|
|
124
|
+
}
|
|
110
125
|
return translate('GlSorting.sortByLabel', 'Sort by:');
|
|
111
126
|
},
|
|
112
127
|
localSortDirection() {
|
|
@@ -121,18 +136,23 @@ var script = {
|
|
|
121
136
|
},
|
|
122
137
|
isDirectionToggleDisabled() {
|
|
123
138
|
var _this$selectedSortOpt3;
|
|
124
|
-
return Boolean((_this$selectedSortOpt3 = this.selectedSortOption) === null || _this$selectedSortOpt3 === void 0 ? void 0 : _this$selectedSortOpt3.directionToggleDisabled);
|
|
139
|
+
return this.disabled || Boolean((_this$selectedSortOpt3 = this.selectedSortOption) === null || _this$selectedSortOpt3 === void 0 ? void 0 : _this$selectedSortOpt3.directionToggleDisabled);
|
|
125
140
|
},
|
|
126
141
|
sortDirectionText() {
|
|
127
|
-
if (this.sortDirectionToolTip) return this.sortDirectionToolTip;
|
|
142
|
+
if (this.sortDirectionToolTip && !this.disabled) return this.sortDirectionToolTip;
|
|
128
143
|
if (this.isDirectionToggleDisabled) {
|
|
129
|
-
return this.selectedSortText ? translate('GlSorting.sortDirectionUnavailableFor', '
|
|
144
|
+
return this.selectedSortText ? translate('GlSorting.sortDirectionUnavailableFor', 'Sorting is unavailable for %{sortField}', {
|
|
130
145
|
sortField: this.selectedSortText
|
|
131
|
-
}) :
|
|
146
|
+
}) : this.unavailableLabel;
|
|
132
147
|
}
|
|
133
148
|
return this.isAscending ? translate('GlSorting.sortAscending', 'Sort direction: ascending') : translate('GlSorting.sortDescending', 'Sort direction: descending');
|
|
134
149
|
}
|
|
135
150
|
},
|
|
151
|
+
watch: {
|
|
152
|
+
disabled(isDisabled) {
|
|
153
|
+
if (isDisabled) this.$refs.listbox.close();
|
|
154
|
+
}
|
|
155
|
+
},
|
|
136
156
|
methods: {
|
|
137
157
|
toggleSortDirection() {
|
|
138
158
|
if (this.isDirectionToggleDisabled) return;
|
|
@@ -149,6 +169,8 @@ var script = {
|
|
|
149
169
|
this.$emit('sort-direction-change', newDirection);
|
|
150
170
|
},
|
|
151
171
|
onSortByChanged(event) {
|
|
172
|
+
if (this.disabled) return;
|
|
173
|
+
|
|
152
174
|
/**
|
|
153
175
|
* Emitted when the sort field is changed.
|
|
154
176
|
*
|
|
@@ -167,7 +189,7 @@ var script = {
|
|
|
167
189
|
const __vue_script__ = script;
|
|
168
190
|
|
|
169
191
|
/* template */
|
|
170
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-button-group',{staticClass:"gl-sorting gl-flex"},[_c('gl-collapsible-listbox',{staticClass:"gl-w-full",class:_vm.dropdownClass,attrs:{"toggle-text":_vm.text,"items":_vm.sortOptions,"selected":_vm.sortBy,"toggle-class":_vm.dropdownToggleClass,"placement":"bottom-end","block":_vm.block,"toggle-id":_vm.toggleId,"toggle-aria-labelled-by":(_vm.sortingListboxId + " " + _vm.toggleId)},on:{"select":_vm.onSortByChanged}}),_vm._v(" "),_c('span',{staticClass:"gl-sr-only",attrs:{"id":_vm.sortingListboxId}},[_vm._v(_vm._s(_vm.sortingListboxLabel))]),_vm._v(" "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],class:['sorting-direction-button', _vm.sortDirectionToggleClass],attrs:{"title":_vm.sortDirectionText,"icon":_vm.localSortDirection,"aria-label":_vm.sortDirectionText,"disabled":_vm.isDirectionToggleDisabled,"accessible-disabled":_vm.isDirectionToggleDisabled},on:{"click":_vm.toggleSortDirection}})],1)};
|
|
192
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-button-group',{staticClass:"gl-sorting gl-flex"},[_c('gl-collapsible-listbox',{ref:"listbox",staticClass:"gl-w-full",class:_vm.dropdownClass,attrs:{"toggle-text":_vm.text,"items":_vm.sortOptions,"selected":_vm.sortBy,"toggle-class":_vm.dropdownToggleClass,"placement":"bottom-end","block":_vm.block,"disabled":_vm.disabled,"toggle-id":_vm.toggleId,"toggle-aria-labelled-by":(_vm.sortingListboxId + " " + _vm.toggleId)},on:{"select":_vm.onSortByChanged}}),_vm._v(" "),_c('span',{staticClass:"gl-sr-only",attrs:{"id":_vm.sortingListboxId}},[_vm._v(_vm._s(_vm.sortingListboxLabel))]),_vm._v(" "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip"}],class:['sorting-direction-button', _vm.sortDirectionToggleClass],attrs:{"title":_vm.sortDirectionText,"icon":_vm.localSortDirection,"aria-label":_vm.sortDirectionText,"disabled":_vm.isDirectionToggleDisabled,"accessible-disabled":_vm.isDirectionToggleDisabled},on:{"click":_vm.toggleSortDirection}})],1)};
|
|
171
193
|
var __vue_staticRenderFns__ = [];
|
|
172
194
|
|
|
173
195
|
/* style */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { uniqueId } from 'lodash-es';
|
|
2
|
+
import { glToggleConfig } from '../../../config';
|
|
2
3
|
import { toggleLabelPosition } from '../../../utils/constants';
|
|
3
4
|
import GlIcon from '../icon/icon';
|
|
4
5
|
import GlLoadingIcon from '../loading_icon/loading_icon';
|
|
@@ -41,6 +42,22 @@ var script = {
|
|
|
41
42
|
required: false,
|
|
42
43
|
default: false
|
|
43
44
|
},
|
|
45
|
+
/**
|
|
46
|
+
* Keep the toggle focusable while `disabled` is `true`. Uses `aria-disabled` so the toggle stays in the tab order and is announced by assistive technology.
|
|
47
|
+
*/
|
|
48
|
+
accessibleDisabled: {
|
|
49
|
+
type: Boolean,
|
|
50
|
+
required: false,
|
|
51
|
+
default: () => glToggleConfig.accessibleDisabledToggle
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Space-separated ids of elements that describe the toggle, in addition to its help text.
|
|
55
|
+
*/
|
|
56
|
+
ariaDescribedby: {
|
|
57
|
+
type: String,
|
|
58
|
+
required: false,
|
|
59
|
+
default: undefined
|
|
60
|
+
},
|
|
44
61
|
/**
|
|
45
62
|
* Whether the toggle is in the loading state.
|
|
46
63
|
*/
|
|
@@ -108,6 +125,12 @@ var script = {
|
|
|
108
125
|
helpId() {
|
|
109
126
|
return this.shouldRenderHelp ? `toggle-help-${this.uuid}` : undefined;
|
|
110
127
|
},
|
|
128
|
+
describedBy() {
|
|
129
|
+
return [this.helpId, this.ariaDescribedby].filter(Boolean).join(' ') || undefined;
|
|
130
|
+
},
|
|
131
|
+
isNativeDisabled() {
|
|
132
|
+
return this.disabled && !this.accessibleDisabled;
|
|
133
|
+
},
|
|
111
134
|
isChecked() {
|
|
112
135
|
return this.value ? 'true' : 'false';
|
|
113
136
|
},
|
|
@@ -146,7 +169,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
|
|
|
146
169
|
'is-checked': _vm.value,
|
|
147
170
|
'is-disabled': _vm.disabled || _vm.isLoading,
|
|
148
171
|
'is-loading': _vm.isLoading,
|
|
149
|
-
},attrs:{"role":"switch","aria-checked":_vm.isChecked,"aria-labelledby":_vm.labelId,"aria-describedby":_vm.
|
|
172
|
+
},attrs:{"role":"switch","aria-checked":_vm.isChecked,"aria-labelledby":_vm.labelId,"aria-describedby":_vm.describedBy,"aria-disabled":_vm.disabled,"type":"button","disabled":_vm.isNativeDisabled},on:{"click":function($event){$event.preventDefault();return _vm.toggleFeature.apply(null, arguments)}}},[(_vm.isLoading)?_c('gl-loading-icon',{staticClass:"toggle-loading",attrs:{"color":"dark"}}):_c('span',{staticClass:"toggle-icon"},[_c('gl-icon',{attrs:{"name":_vm.icon,"size":12}})],1)],1),_vm._v(" "),(_vm.shouldRenderHelp)?_c('span',{staticClass:"gl-help-label",attrs:{"id":_vm.helpId,"data-testid":"toggle-help"}},[_vm._t("help",function(){return [_vm._v(_vm._s(_vm.help))]})],2):_vm._e()])};
|
|
150
173
|
var __vue_staticRenderFns__ = [];
|
|
151
174
|
|
|
152
175
|
/* style */
|
|
@@ -73,6 +73,15 @@ var script = {
|
|
|
73
73
|
type: Boolean,
|
|
74
74
|
required: false,
|
|
75
75
|
default: true
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* A name for the chart that screen readers announce. It is added as a hidden title, which
|
|
79
|
+
* ECharts reads into the description it generates. Ignored when `options` sets a title.
|
|
80
|
+
*/
|
|
81
|
+
accessibleTitle: {
|
|
82
|
+
type: String,
|
|
83
|
+
required: false,
|
|
84
|
+
default: ''
|
|
76
85
|
}
|
|
77
86
|
},
|
|
78
87
|
data() {
|
|
@@ -96,6 +105,14 @@ var script = {
|
|
|
96
105
|
}
|
|
97
106
|
});
|
|
98
107
|
}
|
|
108
|
+
if (this.accessibleTitle && !options.title) {
|
|
109
|
+
options = merge({}, options, {
|
|
110
|
+
title: {
|
|
111
|
+
text: this.accessibleTitle,
|
|
112
|
+
show: false
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
99
116
|
|
|
100
117
|
// Add space at the top to fit the toolbox
|
|
101
118
|
if (((_options$toolbox = options.toolbox) === null || _options$toolbox === void 0 ? void 0 : _options$toolbox.show) === true) {
|
|
@@ -116,6 +133,11 @@ var script = {
|
|
|
116
133
|
this.draw();
|
|
117
134
|
}
|
|
118
135
|
},
|
|
136
|
+
accessibleTitle() {
|
|
137
|
+
if (this.chart) {
|
|
138
|
+
this.draw();
|
|
139
|
+
}
|
|
140
|
+
},
|
|
119
141
|
width() {
|
|
120
142
|
this.setChartSize();
|
|
121
143
|
},
|
package/dist/config.js
CHANGED
|
@@ -5,6 +5,7 @@ const defaultConfig = {
|
|
|
5
5
|
firstDayOfWeek: 0 // Defaults to 0 (Sunday)
|
|
6
6
|
};
|
|
7
7
|
const glButtonConfig = {};
|
|
8
|
+
const glToggleConfig = {};
|
|
8
9
|
let configured = false;
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -15,6 +16,7 @@ let configured = false;
|
|
|
15
16
|
* @property {undefined | Object} translations Generic translations for component labels to fall back to.
|
|
16
17
|
* @property {undefined | Number} firstDayOfWeek Configured first day of the week, from 0 (Sunday) to 6 (Saturday).
|
|
17
18
|
* @property {boolean} [accessibleDisabledButton] Temporary flag to enable the accessible disabled button.
|
|
19
|
+
* @property {boolean} [accessibleDisabledToggle] Temporary flag to enable the accessible disabled toggle.
|
|
18
20
|
*
|
|
19
21
|
*/
|
|
20
22
|
const setConfigs = function () {
|
|
@@ -22,7 +24,9 @@ const setConfigs = function () {
|
|
|
22
24
|
translations = _ref.translations,
|
|
23
25
|
firstDayOfWeek = _ref.firstDayOfWeek,
|
|
24
26
|
_ref$accessibleDisabl = _ref.accessibleDisabledButton,
|
|
25
|
-
accessibleDisabledButton = _ref$accessibleDisabl === void 0 ? false : _ref$accessibleDisabl
|
|
27
|
+
accessibleDisabledButton = _ref$accessibleDisabl === void 0 ? false : _ref$accessibleDisabl,
|
|
28
|
+
_ref$accessibleDisabl2 = _ref.accessibleDisabledToggle,
|
|
29
|
+
accessibleDisabledToggle = _ref$accessibleDisabl2 === void 0 ? false : _ref$accessibleDisabl2;
|
|
26
30
|
if (configured) {
|
|
27
31
|
if (process.env.NODE_ENV === 'development') {
|
|
28
32
|
throw new Error('GitLab UI can only be configured once!');
|
|
@@ -67,6 +71,14 @@ const setConfigs = function () {
|
|
|
67
71
|
accessibleDisabledButton
|
|
68
72
|
});
|
|
69
73
|
}
|
|
74
|
+
|
|
75
|
+
// Temporary flag for the accessible disabled toggle. Once validated, aria-disabled becomes
|
|
76
|
+
// the default for disabled toggles and this flag is removed.
|
|
77
|
+
if (typeof accessibleDisabledToggle === 'boolean') {
|
|
78
|
+
Object.assign(glToggleConfig, {
|
|
79
|
+
accessibleDisabledToggle
|
|
80
|
+
});
|
|
81
|
+
}
|
|
70
82
|
};
|
|
71
83
|
|
|
72
|
-
export { setConfigs as default, defaultConfig, glButtonConfig, i18n };
|
|
84
|
+
export { setConfigs as default, defaultConfig, glButtonConfig, glToggleConfig, i18n };
|
|
@@ -14,9 +14,6 @@ const NAME_FORM = 'BForm';
|
|
|
14
14
|
const NAME_FORM_GROUP = 'BFormGroup';
|
|
15
15
|
const NAME_FORM_INVALID_FEEDBACK = 'BFormInvalidFeedback';
|
|
16
16
|
const NAME_FORM_ROW = 'BFormRow';
|
|
17
|
-
const NAME_FORM_SELECT = 'BFormSelect';
|
|
18
|
-
const NAME_FORM_SELECT_OPTION = 'BFormSelectOption';
|
|
19
|
-
const NAME_FORM_SELECT_OPTION_GROUP = 'BFormSelectOptionGroup';
|
|
20
17
|
const NAME_FORM_TEXT = 'BFormText';
|
|
21
18
|
const NAME_FORM_VALID_FEEDBACK = 'BFormValidFeedback';
|
|
22
19
|
const NAME_LINK = 'BLink';
|
|
@@ -51,4 +48,4 @@ const NAME_TRANSITION = 'BVTransition';
|
|
|
51
48
|
const NAME_TRANSPORTER = 'BVTransporter';
|
|
52
49
|
const NAME_TRANSPORTER_TARGET = 'BVTransporterTarget';
|
|
53
50
|
|
|
54
|
-
export { NAME_BUTTON, NAME_BUTTON_CLOSE, NAME_COL, NAME_DROPDOWN, NAME_DROPDOWN_DIVIDER, NAME_DROPDOWN_FORM, NAME_DROPDOWN_GROUP, NAME_DROPDOWN_HEADER, NAME_DROPDOWN_ITEM, NAME_DROPDOWN_ITEM_BUTTON, NAME_DROPDOWN_TEXT, NAME_FORM, NAME_FORM_BUTTON_LABEL_CONTROL, NAME_FORM_GROUP, NAME_FORM_INVALID_FEEDBACK, NAME_FORM_RATING_STAR, NAME_FORM_ROW,
|
|
51
|
+
export { NAME_BUTTON, NAME_BUTTON_CLOSE, NAME_COL, NAME_DROPDOWN, NAME_DROPDOWN_DIVIDER, NAME_DROPDOWN_FORM, NAME_DROPDOWN_GROUP, NAME_DROPDOWN_HEADER, NAME_DROPDOWN_ITEM, NAME_DROPDOWN_ITEM_BUTTON, NAME_DROPDOWN_TEXT, NAME_FORM, NAME_FORM_BUTTON_LABEL_CONTROL, NAME_FORM_GROUP, NAME_FORM_INVALID_FEEDBACK, NAME_FORM_RATING_STAR, NAME_FORM_ROW, NAME_FORM_TEXT, NAME_FORM_VALID_FEEDBACK, NAME_LINK, NAME_MODAL, NAME_POPOVER, NAME_POPOVER_HELPER, NAME_POPOVER_TEMPLATE, NAME_POPPER, NAME_TAB, NAME_TABLE, NAME_TABLE_CELL, NAME_TABLE_LITE, NAME_TABLE_SIMPLE, NAME_TABS, NAME_TAB_BUTTON_HELPER, NAME_TBODY, NAME_TFOOT, NAME_TH, NAME_THEAD, NAME_TOAST, NAME_TOASTER, NAME_TOAST_POP, NAME_TOOLTIP, NAME_TOOLTIP_HELPER, NAME_TOOLTIP_TEMPLATE, NAME_TR, NAME_TRANSITION, NAME_TRANSPORTER, NAME_TRANSPORTER_TARGET };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "138.
|
|
3
|
+
"version": "138.2.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -89,14 +89,6 @@
|
|
|
89
89
|
"tailwindcss": "^3",
|
|
90
90
|
"vue": "^2.7.16"
|
|
91
91
|
},
|
|
92
|
-
"resolutions": {
|
|
93
|
-
"chokidar": "^4.0.3",
|
|
94
|
-
"sane": "^5.0.1",
|
|
95
|
-
"jackspeak": "2.3.6",
|
|
96
|
-
"postcss": "8.5.28",
|
|
97
|
-
"json5": "2.2.3",
|
|
98
|
-
"rollup-plugin-vue/@vue/component-compiler/postcss-modules-sync/generic-names/loader-utils": "3.3.1"
|
|
99
|
-
},
|
|
100
92
|
"devDependencies": {
|
|
101
93
|
"@adobe/leonardo-contrast-colors": "^1.1.0",
|
|
102
94
|
"@babel/core": "^7.29.7",
|
|
@@ -107,7 +99,7 @@
|
|
|
107
99
|
"@cypress/grep": "^4.1.1",
|
|
108
100
|
"@figma/code-connect": "^1.5.3",
|
|
109
101
|
"@gitlab/fonts": "^1.3.1",
|
|
110
|
-
"@gitlab/hybrid-vue": "npm:@vue/compat@3.5.
|
|
102
|
+
"@gitlab/hybrid-vue": "npm:@vue/compat@3.5.42",
|
|
111
103
|
"@gitlab/svgs": "*",
|
|
112
104
|
"@gitlab/vue-router-vue3": "npm:vue-router@^4.6.4",
|
|
113
105
|
"@jest/test-sequencer": "30.5.2",
|
|
@@ -170,7 +162,7 @@
|
|
|
170
162
|
"rollup-plugin-string": "^3.0.0",
|
|
171
163
|
"rollup-plugin-svg": "^2.0.0",
|
|
172
164
|
"rollup-plugin-vue": "^5.1.9",
|
|
173
|
-
"sass": "^1.105.
|
|
165
|
+
"sass": "^1.105.1",
|
|
174
166
|
"sass-loader": "^10.5.2",
|
|
175
167
|
"sass-true": "^9",
|
|
176
168
|
"start-server-and-test": "^2.1.5",
|