@gitlab/ui 38.12.0 → 39.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # [39.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v38.12.0...v39.0.0) (2022-04-21)
2
+
3
+
4
+ ### Reverts
5
+
6
+ * add character counter to gl-form-textarea ([70a7a3f](https://gitlab.com/gitlab-org/gitlab-ui/commit/70a7a3fd9c2729b739020d167043490da72a556b))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * The feature added in
12
+ https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2738 has been
13
+ removed, as it causes complications regarding a validator used in
14
+ GitLab. This feature will be reconsidered and re-implemented later.
15
+
1
16
  # [38.12.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v38.11.0...v38.12.0) (2022-04-21)
2
17
 
3
18
 
@@ -1,6 +1,4 @@
1
1
  import { BFormTextarea } from 'bootstrap-vue/esm/index.js';
2
- import GlSprintf from '../../../utilities/sprintf/sprintf';
3
- import { textareaCountOptions } from '../../../../utils/constants';
4
2
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
5
3
 
6
4
  const model = {
@@ -9,8 +7,7 @@ const model = {
9
7
  };
10
8
  var script = {
11
9
  components: {
12
- BFormTextarea,
13
- GlSprintf
10
+ BFormTextarea
14
11
  },
15
12
  inheritAttrs: false,
16
13
  model,
@@ -31,27 +28,6 @@ var script = {
31
28
  type: Boolean,
32
29
  required: false,
33
30
  default: false
34
- },
35
- count: {
36
- type: Number,
37
- required: false,
38
- default: 0
39
- },
40
- countType: {
41
- required: false,
42
- type: String,
43
- default: textareaCountOptions.max,
44
- validator: value => Object.keys(textareaCountOptions).includes(value)
45
- },
46
- characterCountText: {
47
- required: false,
48
- type: String,
49
- default: ''
50
- },
51
- characterCountOverLimitText: {
52
- required: false,
53
- type: String,
54
- default: ''
55
31
  }
56
32
  },
57
33
  computed: {
@@ -88,42 +64,6 @@ var script = {
88
64
 
89
65
  keypressEvent() {
90
66
  return this.submitOnEnter ? 'keyup' : null;
91
- },
92
-
93
- characters() {
94
- return this.value.length;
95
- },
96
-
97
- remainingCharacters() {
98
- if (this.count) {
99
- return Math.abs(this.count - this.characters);
100
- }
101
-
102
- return null;
103
- },
104
-
105
- characterCountClasses() {
106
- switch (this.countType) {
107
- case textareaCountOptions.max:
108
- return {
109
- 'gl-text-red-500': this.value.length > this.count,
110
- 'gl-text-gray-500': this.value.length <= this.count
111
- };
112
-
113
- case textareaCountOptions.recommended:
114
- return 'gl-text-gray-500';
115
-
116
- default:
117
- return {};
118
- }
119
- },
120
-
121
- hasCount() {
122
- return this.remainingCharacters != null;
123
- },
124
-
125
- characterCountMessage() {
126
- return this.characters > this.count ? this.characterCountOverLimitText : this.characterCountText;
127
67
  }
128
68
 
129
69
  },
@@ -141,7 +81,7 @@ var script = {
141
81
  const __vue_script__ = script;
142
82
 
143
83
  /* template */
144
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('b-form-textarea',_vm._g(_vm._b({ref:"textarea",staticClass:"gl-form-input gl-form-textarea",attrs:{"no-resize":_vm.noResize,"value":_vm.value},nativeOn:_vm._d({},[_vm.keypressEvent,function($event){return _vm.handleKeyPress($event)}])},'b-form-textarea',_vm.$attrs,false),_vm.listeners)),_vm._v(" "),(_vm.hasCount)?_c('div',[_c('small',{class:_vm.characterCountClasses,attrs:{"aria-live":"polite"}},[_c('gl-sprintf',{attrs:{"message":_vm.characterCountMessage},scopedSlots:_vm._u([{key:"count",fn:function(){return [_vm._v(_vm._s(_vm.remainingCharacters))]},proxy:true}],null,false,2559963941)})],1)]):_vm._e()],1)};
84
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-form-textarea',_vm._g(_vm._b({staticClass:"gl-form-input gl-form-textarea",attrs:{"no-resize":_vm.noResize,"value":_vm.value},nativeOn:_vm._d({},[_vm.keypressEvent,function($event){return _vm.handleKeyPress($event)}])},'b-form-textarea',_vm.$attrs,false),_vm.listeners))};
145
85
  var __vue_staticRenderFns__ = [];
146
86
 
147
87
  /* style */
@@ -251,9 +251,5 @@ const loadingIconSizes = {
251
251
  'lg (32x32)': 'lg',
252
252
  'xl (64x64)': 'xl'
253
253
  };
254
- const textareaCountOptions = {
255
- max: 'max',
256
- recommended: 'recommended'
257
- };
258
254
 
259
- export { COMMA, alertVariantIconMap, alertVariantOptions, alignOptions, avatarShapeOptions, avatarSizeOptions, avatarsInlineSizeOptions, badgeForButtonOptions, badgeSizeOptions, badgeVariantOptions, bannerVariants, buttonCategoryOptions, buttonSizeOptions, buttonSizeOptionsMap, buttonVariantOptions, colorThemes, columnOptions, defaultDateFormat, drawerVariants, dropdownVariantOptions, focusableTags, formInputSizes, formStateOptions, glThemes, iconSizeOptions, keyboard, labelColorOptions, labelSizeOptions, loadingIconSizes, maxZIndex, modalButtonDefaults, modalSizeOptions, popoverPlacements, resizeDebounceTime, sizeOptions, sizeOptionsWithNoDefault, tabsButtonDefaults, targetOptions, textareaCountOptions, toggleLabelPosition, tokenVariants, tooltipActionEvents, tooltipDelay, tooltipPlacements, triggerVariantOptions, truncateOptions, variantCssColorMap, variantOptions, variantOptionsWithNoDefault, viewModeOptions };
255
+ export { COMMA, alertVariantIconMap, alertVariantOptions, alignOptions, avatarShapeOptions, avatarSizeOptions, avatarsInlineSizeOptions, badgeForButtonOptions, badgeSizeOptions, badgeVariantOptions, bannerVariants, buttonCategoryOptions, buttonSizeOptions, buttonSizeOptionsMap, buttonVariantOptions, colorThemes, columnOptions, defaultDateFormat, drawerVariants, dropdownVariantOptions, focusableTags, formInputSizes, formStateOptions, glThemes, iconSizeOptions, keyboard, labelColorOptions, labelSizeOptions, loadingIconSizes, maxZIndex, modalButtonDefaults, modalSizeOptions, popoverPlacements, resizeDebounceTime, sizeOptions, sizeOptionsWithNoDefault, tabsButtonDefaults, targetOptions, toggleLabelPosition, tokenVariants, tooltipActionEvents, tooltipDelay, tooltipPlacements, triggerVariantOptions, truncateOptions, variantCssColorMap, variantOptions, variantOptionsWithNoDefault, viewModeOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "38.12.0",
3
+ "version": "39.0.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -1,5 +1,4 @@
1
1
  import { mount } from '@vue/test-utils';
2
- import { textareaCountOptions } from '../../../../utils/constants';
3
2
  import GlFormTextarea from './form_textarea.vue';
4
3
 
5
4
  const modelEvent = GlFormTextarea.model.event;
@@ -7,13 +6,11 @@ const newValue = 'foo';
7
6
 
8
7
  describe('GlFormTextArea', () => {
9
8
  let wrapper;
10
- let textarea;
11
9
 
12
10
  const createComponent = (propsData = {}) => {
13
11
  wrapper = mount(GlFormTextarea, {
14
12
  propsData,
15
13
  });
16
- textarea = wrapper.find('textarea');
17
14
  };
18
15
 
19
16
  describe('v-model', () => {
@@ -23,7 +20,7 @@ describe('GlFormTextArea', () => {
23
20
  });
24
21
 
25
22
  it(`sets the textarea's value`, () => {
26
- expect(textarea.element.value).toBe('initial');
23
+ expect(wrapper.element.value).toBe('initial');
27
24
  });
28
25
 
29
26
  describe('when the value prop changes', () => {
@@ -33,7 +30,7 @@ describe('GlFormTextArea', () => {
33
30
  });
34
31
 
35
32
  it(`updates the textarea's value`, () => {
36
- expect(textarea.element.value).toBe(newValue);
33
+ expect(wrapper.element.value).toBe(newValue);
37
34
  });
38
35
  });
39
36
  });
@@ -42,7 +39,7 @@ describe('GlFormTextArea', () => {
42
39
  beforeEach(() => {
43
40
  createComponent();
44
41
 
45
- textarea.setValue(newValue);
42
+ wrapper.setValue(newValue);
46
43
  });
47
44
 
48
45
  it('synchronously emits update event', () => {
@@ -62,7 +59,7 @@ describe('GlFormTextArea', () => {
62
59
 
63
60
  createComponent({ debounce });
64
61
 
65
- textarea.setValue(newValue);
62
+ wrapper.setValue(newValue);
66
63
  });
67
64
 
68
65
  it('synchronously emits an update event', () => {
@@ -85,7 +82,7 @@ describe('GlFormTextArea', () => {
85
82
  beforeEach(() => {
86
83
  createComponent({ lazy: true });
87
84
 
88
- textarea.setValue(newValue);
85
+ wrapper.setValue(newValue);
89
86
  });
90
87
 
91
88
  it('synchronously emits an update event', () => {
@@ -95,7 +92,7 @@ describe('GlFormTextArea', () => {
95
92
  it.each(['change', 'blur'])('updates model after %s event', (event) => {
96
93
  expect(wrapper.emitted(modelEvent)).toBe(undefined);
97
94
 
98
- textarea.trigger(event);
95
+ wrapper.trigger(event);
99
96
 
100
97
  expect(wrapper.emitted(modelEvent)).toEqual([[newValue]]);
101
98
  });
@@ -105,7 +102,7 @@ describe('GlFormTextArea', () => {
105
102
  it('should be false by default', () => {
106
103
  createComponent({});
107
104
 
108
- textarea.trigger('keyup.enter', {
105
+ wrapper.trigger('keyup.enter', {
109
106
  metaKey: true,
110
107
  });
111
108
 
@@ -115,115 +112,11 @@ describe('GlFormTextArea', () => {
115
112
  it('should emit submit when cmd+enter is pressed', async () => {
116
113
  createComponent({ submitOnEnter: true });
117
114
 
118
- textarea.trigger('keyup.enter', {
115
+ wrapper.trigger('keyup.enter', {
119
116
  metaKey: true,
120
117
  });
121
118
 
122
119
  expect(wrapper.emitted().submit).toEqual([[]]);
123
120
  });
124
121
  });
125
-
126
- describe('count', () => {
127
- it('should be 0 by default', () => {
128
- createComponent({
129
- characterCountText: '%{count} characters left',
130
- characterCountOverLimitText: '%{count} characters over limit',
131
- });
132
-
133
- expect(wrapper.text()).not.toContain('characters left');
134
- expect(wrapper.text()).not.toContain('characters over limit');
135
- });
136
-
137
- it('should display the remaining characters when a count is provided', () => {
138
- createComponent({
139
- count: 400,
140
- characterCountText: '%{count} characters left',
141
- characterCountOverLimitText: '%{count} characters over limit',
142
- });
143
-
144
- expect(wrapper.text()).toContain('400 characters left');
145
- });
146
-
147
- it('should display the difference between the limit and the length of the value', () => {
148
- const value = 'hello';
149
-
150
- createComponent({
151
- value,
152
- count: 400,
153
- characterCountText: '%{count} characters left',
154
- characterCountOverLimitText: '%{count} characters over limit',
155
- });
156
-
157
- const { length } = value;
158
-
159
- expect(wrapper.text()).toContain(`${400 - length} characters left`);
160
- });
161
-
162
- it('should display the over limit text once over the limit', () => {
163
- const value = 'hello';
164
- const count = 4;
165
-
166
- createComponent({
167
- value,
168
- count,
169
- characterCountText: '%{count} characters left',
170
- characterCountOverLimitText: '%{count} characters over limit',
171
- });
172
-
173
- const diff = Math.abs(count - value.length);
174
-
175
- expect(wrapper.text()).toContain(`${diff} characters over limit`);
176
- });
177
-
178
- describe('max', () => {
179
- it('should display the text as grey when up to the limit', () => {
180
- const value = 'hello';
181
- const count = 5;
182
-
183
- createComponent({
184
- value,
185
- count,
186
- characterCountText: '%{count} characters left',
187
- characterCountOverLimitText: '%{count} characters over limit',
188
- });
189
-
190
- const small = wrapper.find('small');
191
-
192
- expect(small.classes()).toContain('gl-text-gray-500');
193
- });
194
- it('should display the text as danger when over the limit', () => {
195
- const value = 'hello';
196
- const count = 4;
197
-
198
- createComponent({
199
- value,
200
- count,
201
- characterCountText: '%{count} characters left',
202
- characterCountOverLimitText: '%{count} characters over limit',
203
- });
204
-
205
- const small = wrapper.find('small');
206
-
207
- expect(small.classes()).toContain('gl-text-red-500');
208
- });
209
- });
210
- describe('recommended', () => {
211
- it('should display the text as gray when over the limit', () => {
212
- const value = 'hello';
213
- const count = 4;
214
-
215
- createComponent({
216
- value,
217
- count,
218
- countType: textareaCountOptions.recommended,
219
- characterCountText: '%{count} characters left',
220
- characterCountOverLimitText: '%{count} characters over limit',
221
- });
222
-
223
- const small = wrapper.find('small');
224
-
225
- expect(small.classes()).toContain('gl-text-gray-500');
226
- });
227
- });
228
- });
229
122
  });
@@ -1,5 +1,4 @@
1
1
  import { GlFormTextarea } from '../../../../index';
2
- import { textareaCountOptions } from '../../../../utils/constants';
3
2
  import readme from './form_textarea.md';
4
3
 
5
4
  const template = `
@@ -8,10 +7,6 @@ const template = `
8
7
  :placeholder="placeholder"
9
8
  :rows="5"
10
9
  :no-resize="noResize"
11
- :count="count"
12
- :countType="countType"
13
- :character-count-text="characterCountText"
14
- :character-count-over-limit-text="characterCountOverLimitText"
15
10
  />
16
11
  `;
17
12
 
@@ -19,18 +14,10 @@ const generateProps = ({
19
14
  model = 'We take inspiration from other companies, and we always go for the boring solutions. Just like the rest of our work, we continually adjust our values and strive always to make them better. We used to have more values, but it was difficult to remember them all, so we condensed them and gave sub-values and created an acronym. Everyone is welcome to suggest improvements.',
20
15
  placeholder = 'hello',
21
16
  noResize = GlFormTextarea.props.noResize.default,
22
- count = 400,
23
- countType = textareaCountOptions.max,
24
- characterCountText = '%{count} characters left',
25
- characterCountOverLimitText = '%{count} characters over limit',
26
17
  } = {}) => ({
27
18
  model,
28
19
  placeholder,
29
20
  noResize,
30
- count,
31
- countType,
32
- characterCountText,
33
- characterCountOverLimitText,
34
21
  });
35
22
 
36
23
  const Template = (args) => ({
@@ -54,12 +41,4 @@ export default {
54
41
  },
55
42
  },
56
43
  },
57
- argTypes: {
58
- countType: {
59
- control: {
60
- type: 'select',
61
- options: textareaCountOptions,
62
- },
63
- },
64
- },
65
44
  };
@@ -1,7 +1,5 @@
1
1
  <script>
2
2
  import { BFormTextarea } from 'bootstrap-vue';
3
- import GlSprintf from '../../../utilities/sprintf/sprintf.vue';
4
- import { textareaCountOptions } from '../../../../utils/constants';
5
3
 
6
4
  const model = {
7
5
  prop: 'value',
@@ -11,7 +9,6 @@ const model = {
11
9
  export default {
12
10
  components: {
13
11
  BFormTextarea,
14
- GlSprintf,
15
12
  },
16
13
  inheritAttrs: false,
17
14
  model,
@@ -33,27 +30,6 @@ export default {
33
30
  required: false,
34
31
  default: false,
35
32
  },
36
- count: {
37
- type: Number,
38
- required: false,
39
- default: 0,
40
- },
41
- countType: {
42
- required: false,
43
- type: String,
44
- default: textareaCountOptions.max,
45
- validator: (value) => Object.keys(textareaCountOptions).includes(value),
46
- },
47
- characterCountText: {
48
- required: false,
49
- type: String,
50
- default: '',
51
- },
52
- characterCountOverLimitText: {
53
- required: false,
54
- type: String,
55
- default: '',
56
- },
57
33
  },
58
34
  computed: {
59
35
  listeners() {
@@ -80,37 +56,6 @@ export default {
80
56
  keypressEvent() {
81
57
  return this.submitOnEnter ? 'keyup' : null;
82
58
  },
83
- characters() {
84
- return this.value.length;
85
- },
86
- remainingCharacters() {
87
- if (this.count) {
88
- return Math.abs(this.count - this.characters);
89
- }
90
-
91
- return null;
92
- },
93
- characterCountClasses() {
94
- switch (this.countType) {
95
- case textareaCountOptions.max:
96
- return {
97
- 'gl-text-red-500': this.value.length > this.count,
98
- 'gl-text-gray-500': this.value.length <= this.count,
99
- };
100
- case textareaCountOptions.recommended:
101
- return 'gl-text-gray-500';
102
- default:
103
- return {};
104
- }
105
- },
106
- hasCount() {
107
- return this.remainingCharacters != null;
108
- },
109
- characterCountMessage() {
110
- return this.characters > this.count
111
- ? this.characterCountOverLimitText
112
- : this.characterCountText;
113
- },
114
59
  },
115
60
  methods: {
116
61
  handleKeyPress(e) {
@@ -123,22 +68,12 @@ export default {
123
68
  </script>
124
69
 
125
70
  <template>
126
- <div>
127
- <b-form-textarea
128
- ref="textarea"
129
- class="gl-form-input gl-form-textarea"
130
- :no-resize="noResize"
131
- v-bind="$attrs"
132
- :value="value"
133
- v-on="listeners"
134
- @[keypressEvent].native="handleKeyPress"
135
- />
136
- <div v-if="hasCount">
137
- <small :class="characterCountClasses" aria-live="polite">
138
- <gl-sprintf :message="characterCountMessage">
139
- <template #count>{{ remainingCharacters }}</template>
140
- </gl-sprintf>
141
- </small>
142
- </div>
143
- </div>
71
+ <b-form-textarea
72
+ class="gl-form-input gl-form-textarea"
73
+ :no-resize="noResize"
74
+ v-bind="$attrs"
75
+ :value="value"
76
+ v-on="listeners"
77
+ @[keypressEvent].native="handleKeyPress"
78
+ />
144
79
  </template>
@@ -298,8 +298,3 @@ export const loadingIconSizes = {
298
298
  'lg (32x32)': 'lg',
299
299
  'xl (64x64)': 'xl',
300
300
  };
301
-
302
- export const textareaCountOptions = {
303
- max: 'max',
304
- recommended: 'recommended',
305
- };