@gitlab/ui 111.5.0 → 111.6.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,15 @@
1
+ # [111.6.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v111.5.0...v111.6.0) (2025-03-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **GlLink:** fix passing of attributes to Vue 3 RouterLink ([0e2632d](https://gitlab.com/gitlab-org/gitlab-ui/commit/0e2632d609985500713c1c10dbe48548eb1f4317))
7
+
8
+
9
+ ### Features
10
+
11
+ * **GlDatepicker:** Add global firstDay config ([4b3c9a8](https://gitlab.com/gitlab-org/gitlab-ui/commit/4b3c9a8fc21b534245274d30dee86562d48250bb))
12
+
1
13
  # [111.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v111.4.0...v111.5.0) (2025-03-20)
2
14
 
3
15
 
@@ -1,15 +1,14 @@
1
- import uniqueId from 'lodash/uniqueId';
2
1
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
3
2
 
4
3
  var script = {
5
4
  name: 'GlAccordion',
6
5
  provide() {
7
- const accordionId = uniqueId('accordion-set-');
8
- // temporary fix for this issue: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2019#note_514671251
9
- // MR for the upstream pending: https://github.com/vuejs/apollo/pull/1153
10
6
  return {
7
+ // temporary fix for this issue: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2019#note_514671251
8
+ // MR for the upstream pending: https://github.com/vuejs/apollo/pull/1153
9
+ // Track removing this workaround in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/3152
11
10
  defaultHeaderLevel: () => this.headerLevel,
12
- accordionSetId: () => this.autoCollapse && accordionId
11
+ autoCollapse: () => this.autoCollapse
13
12
  };
14
13
  },
15
14
  props: {
@@ -1,21 +1,18 @@
1
1
  import uniqueId from 'lodash/uniqueId';
2
- import { BCollapse } from '../../../vendor/bootstrap-vue/src/components/collapse/collapse';
2
+ import GlCollapse from '../collapse/collapse';
3
3
  import GlAnimatedChevronRightDownIcon from '../animated_icon/animated_chevron_right_down_icon';
4
- import { GlCollapseToggleDirective } from '../../../directives/collapse_toggle';
5
4
  import GlButton from '../button/button';
5
+ import { COLLAPSE_EVENT } from './constants';
6
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
7
7
 
8
8
  var script = {
9
9
  name: 'GlAccordionItem',
10
10
  components: {
11
- BCollapse,
11
+ GlCollapse,
12
12
  GlButton,
13
13
  GlAnimatedChevronRightDownIcon
14
14
  },
15
- directives: {
16
- GlCollapseToggle: GlCollapseToggleDirective
17
- },
18
- inject: ['accordionSetId', 'defaultHeaderLevel'],
15
+ inject: ['defaultHeaderLevel', 'autoCollapse'],
19
16
  inheritAttrs: false,
20
17
  model: {
21
18
  prop: 'visible',
@@ -68,7 +65,7 @@ var script = {
68
65
  data() {
69
66
  return {
70
67
  accordionItemId: uniqueId('accordion-item-'),
71
- isVisible: this.visible
68
+ localVisible: this.visible
72
69
  };
73
70
  },
74
71
  computed: {
@@ -76,18 +73,49 @@ var script = {
76
73
  const level = this.headerLevel || this.defaultHeaderLevel();
77
74
  return `h${level}`;
78
75
  },
79
- accordion() {
80
- return this.accordionSetId() || undefined;
81
- },
82
76
  buttonTitle() {
83
- return this.isVisible && this.titleVisible ? this.titleVisible : this.title;
77
+ return this.localVisible && this.titleVisible ? this.titleVisible : this.title;
84
78
  }
85
79
  },
86
80
  watch: {
87
- isVisible: {
88
- immediate: true,
89
- handler(isVisible) {
90
- this.$emit('input', isVisible);
81
+ visible: {
82
+ handler(newVisible) {
83
+ this.localVisible = newVisible;
84
+ this.checkAndCollapseSiblingAccordionItems(newVisible);
85
+ }
86
+ }
87
+ },
88
+ created() {
89
+ this.$emit('input', this.localVisible);
90
+ },
91
+ mounted() {
92
+ this.$parent.$el.addEventListener(COLLAPSE_EVENT, this.onParentCollapse);
93
+ },
94
+ beforeDestroy() {
95
+ this.$parent.$el.removeEventListener(COLLAPSE_EVENT, this.onParentCollapse);
96
+ },
97
+ methods: {
98
+ onParentCollapse(_ref) {
99
+ let {
100
+ detail: accordionItemId
101
+ } = _ref;
102
+ if (accordionItemId === this.accordionItemId) {
103
+ return;
104
+ }
105
+ this.$emit('input', false);
106
+ this.localVisible = false;
107
+ },
108
+ onButtonClick() {
109
+ const newLocalVisible = !this.localVisible;
110
+ this.$emit('input', newLocalVisible);
111
+ this.localVisible = newLocalVisible;
112
+ this.checkAndCollapseSiblingAccordionItems(newLocalVisible);
113
+ },
114
+ checkAndCollapseSiblingAccordionItems(newVisible) {
115
+ if (this.autoCollapse() && newVisible) {
116
+ this.$parent.$el.dispatchEvent(new CustomEvent(COLLAPSE_EVENT, {
117
+ detail: this.accordionItemId
118
+ }));
91
119
  }
92
120
  }
93
121
  }
@@ -97,7 +125,7 @@ var script = {
97
125
  const __vue_script__ = script;
98
126
 
99
127
  /* template */
100
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-accordion-item"},[_c(_vm.headerComponent,{tag:"component",staticClass:"gl-accordion-item-header",class:_vm.headerClass},[_c('gl-button',{directives:[{name:"gl-collapse-toggle",rawName:"v-gl-collapse-toggle",value:(_vm.accordionItemId),expression:"accordionItemId"}],attrs:{"variant":"link","button-text-classes":"gl-flex"}},[_c('gl-animated-chevron-right-down-icon',{attrs:{"is-on":_vm.isVisible}}),_vm._v("\n "+_vm._s(_vm.buttonTitle)+"\n ")],1)],1),_vm._v(" "),_c('b-collapse',{staticClass:"gl-mt-3 gl-text-base",attrs:{"id":_vm.accordionItemId,"visible":_vm.isVisible,"accordion":_vm.accordion,"data-testid":("accordion-item-collapse-" + _vm.accordionItemId)},model:{value:(_vm.isVisible),callback:function ($$v) {_vm.isVisible=$$v;},expression:"isVisible"}},[_vm._t("default")],2)],1)};
128
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-accordion-item"},[_c(_vm.headerComponent,{tag:"component",staticClass:"gl-accordion-item-header",class:_vm.headerClass},[_c('gl-button',{attrs:{"variant":"link","button-text-classes":"gl-flex","aria-expanded":_vm.localVisible ? 'true' : 'false',"aria-controls":_vm.accordionItemId},on:{"click":_vm.onButtonClick}},[_c('gl-animated-chevron-right-down-icon',{attrs:{"is-on":_vm.localVisible}}),_vm._v("\n "+_vm._s(_vm.buttonTitle)+"\n ")],1)],1),_vm._v(" "),_c('gl-collapse',{attrs:{"id":_vm.accordionItemId,"data-testid":("accordion-item-collapse-" + _vm.accordionItemId)},model:{value:(_vm.localVisible),callback:function ($$v) {_vm.localVisible=$$v;},expression:"localVisible"}},[_c('div',{staticClass:"gl-mt-3 gl-text-base"},[_vm._t("default")],2)])],1)};
101
129
  var __vue_staticRenderFns__ = [];
102
130
 
103
131
  /* style */
@@ -0,0 +1,3 @@
1
+ const COLLAPSE_EVENT = 'collapse';
2
+
3
+ export { COLLAPSE_EVENT };
@@ -1,5 +1,6 @@
1
1
  import isString from 'lodash/isString';
2
2
  import Pikaday from 'pikaday';
3
+ import { defaultConfig } from '../../../config';
3
4
  import { defaultDateFormat, datepickerWidthOptionsMap } from '../../../utils/constants';
4
5
  import { areDatesEqual } from '../../../utils/datetime_utility';
5
6
  import GlButton from '../button/button';
@@ -119,7 +120,7 @@ var script = {
119
120
  firstDay: {
120
121
  type: Number,
121
122
  required: false,
122
- default: 0
123
+ default: () => defaultConfig.firstDayOfWeek || 0 // Defaults to 0 (Sunday)
123
124
  },
124
125
  ariaLabel: {
125
126
  type: String,
@@ -22,6 +22,7 @@ var script = {
22
22
  directives: {
23
23
  SafeLink: SafeLinkDirective
24
24
  },
25
+ inheritAttrs: false,
25
26
  props: {
26
27
  /**
27
28
  * Denotes the target URL of the link for standard links.
@@ -189,15 +190,22 @@ var script = {
189
190
  return fallback;
190
191
  },
191
192
  computedProps() {
193
+ const baseRouterLinkProps = {
194
+ to: this.to,
195
+ activeClass: this.activeClass,
196
+ exactActiveClass: this.exactActiveClass,
197
+ replace: this.replace,
198
+ ...(isBoolean(this.prefetch) ? {
199
+ prefetch: this.prefetch
200
+ } : {})
201
+ };
192
202
  if (this.isRouterLink) {
203
+ if (this.isVue3RouterLink) {
204
+ return baseRouterLinkProps;
205
+ }
193
206
  return {
194
- to: this.to,
195
- activeClass: this.activeClass,
196
- exactActiveClass: this.exactActiveClass,
197
- replace: this.replace,
198
- ...(isBoolean(this.prefetch) ? {
199
- prefetch: this.prefetch
200
- } : {})
207
+ ...baseRouterLinkProps,
208
+ ...this.$attrs
201
209
  };
202
210
  }
203
211
  return {
@@ -208,7 +216,8 @@ var script = {
208
216
  } : {}),
209
217
  rel: this.rel,
210
218
  target: this.target,
211
- href: this.computedHref
219
+ href: this.computedHref,
220
+ ...this.$attrs
212
221
  };
213
222
  },
214
223
  computedListeners() {
@@ -293,7 +302,7 @@ var _obj;
293
302
  var routerLinkHref = ref.href;
294
303
  var isActive = ref.isActive;
295
304
  var isExactActive = ref.isExactActive;
296
- var navigate = ref.navigate;return [_c('a',_vm._g({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],class:[_vm.computedClass, ( _obj = {}, _obj[_vm.activeClass] = isActive, _obj[_vm.exactActiveClass] = isExactActive, _obj )],attrs:{"href":routerLinkHref},on:{"click":function($event){return _vm.onClick($event, navigate)}}},_vm.computedListeners),[_vm._t("default")],2)]}}],null,true)},'component',_vm.computedProps,false)):(_vm.isRouterLink)?_c(_vm.tag,_vm._g(_vm._b({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],tag:"component",class:_vm.computedClass,nativeOn:{"click":function($event){return _vm.onClick.apply(null, arguments)}}},'component',_vm.computedProps,false),_vm.computedListeners),[_vm._t("default")],2):_c(_vm.tag,_vm._g(_vm._b({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],tag:"component",class:_vm.computedClass,on:{"click":_vm.onClick}},'component',_vm.computedProps,false),_vm.computedListeners),[_vm._t("default")],2)};
305
+ var navigate = ref.navigate;return [_c('a',_vm._g(_vm._b({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],class:[_vm.computedClass, ( _obj = {}, _obj[_vm.activeClass] = isActive, _obj[_vm.exactActiveClass] = isExactActive, _obj )],attrs:{"href":routerLinkHref},on:{"click":function($event){return _vm.onClick($event, navigate)}}},'a',_vm.$attrs,false),_vm.computedListeners),[_vm._t("default")],2)]}}],null,true)},'component',_vm.computedProps,false)):(_vm.isRouterLink)?_c(_vm.tag,_vm._g(_vm._b({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],tag:"component",class:_vm.computedClass,nativeOn:{"click":function($event){return _vm.onClick.apply(null, arguments)}}},'component',_vm.computedProps,false),_vm.computedListeners),[_vm._t("default")],2):_c(_vm.tag,_vm._g(_vm._b({directives:[{name:"safe-link",rawName:"v-safe-link:[safeLinkConfig]",arg:_vm.safeLinkConfig}],tag:"component",class:_vm.computedClass,on:{"click":_vm.onClick}},'component',_vm.computedProps,false),_vm.computedListeners),[_vm._t("default")],2)};
297
306
  var __vue_staticRenderFns__ = [];
298
307
 
299
308
  /* style */
package/dist/config.js CHANGED
@@ -32,6 +32,9 @@ try {
32
32
  // localStorage doesn't exist (or the value is not properly formatted)
33
33
  }
34
34
  const i18n = translationKeys;
35
+ const defaultConfig = {
36
+ firstDayOfWeek: 0 // Defaults to 0 (Sunday)
37
+ };
35
38
  let configured = false;
36
39
 
37
40
  /**
@@ -40,10 +43,12 @@ let configured = false;
40
43
  * @typedef {object} GitLabUIConfiguration
41
44
  * @template TValue=string
42
45
  * @property {undefined | Object} translations Generic translations for component labels to fall back to.
46
+ * @property {undefined | Number} firstDayOfWeek Configured first day of the week, from 0 (Sunday) to 6 (Saturday).
43
47
  */
44
48
  const setConfigs = function () {
45
49
  let {
46
- translations
50
+ translations,
51
+ firstDayOfWeek
47
52
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
48
53
  if (configured) {
49
54
  if (process.env.NODE_ENV === 'development') {
@@ -58,6 +63,9 @@ const setConfigs = function () {
58
63
  delay: popoverDelayConfig
59
64
  }
60
65
  });
66
+ if (typeof firstDayOfWeek === 'number' && firstDayOfWeek >= 0 && firstDayOfWeek <= 6) {
67
+ defaultConfig.firstDayOfWeek = firstDayOfWeek;
68
+ }
61
69
  if (typeof translations === 'object') {
62
70
  if (process.env.NODE_ENV === 'development') {
63
71
  const undefinedTranslationKeys = Object.keys(i18n).reduce((acc, current) => {
@@ -78,4 +86,4 @@ const setConfigs = function () {
78
86
  };
79
87
 
80
88
  export default setConfigs;
81
- export { i18n };
89
+ export { defaultConfig, i18n };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "111.5.0",
3
+ "version": "111.6.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -170,8 +170,8 @@
170
170
  "npm-run-all": "^4.1.5",
171
171
  "patch-package": "^8.0.0",
172
172
  "pikaday": "^1.8.0",
173
- "playwright": "^1.51.0",
174
- "playwright-core": "^1.51.0",
173
+ "playwright": "^1.51.1",
174
+ "playwright-core": "^1.51.1",
175
175
  "postcss": "8.4.28",
176
176
  "postcss-loader": "^7.0.2",
177
177
  "postcss-scss": "4.0.4",
@@ -1,15 +1,13 @@
1
1
  <script>
2
- import uniqueId from 'lodash/uniqueId';
3
-
4
2
  export default {
5
3
  name: 'GlAccordion',
6
4
  provide() {
7
- const accordionId = uniqueId('accordion-set-');
8
- // temporary fix for this issue: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2019#note_514671251
9
- // MR for the upstream pending: https://github.com/vuejs/apollo/pull/1153
10
5
  return {
6
+ // temporary fix for this issue: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2019#note_514671251
7
+ // MR for the upstream pending: https://github.com/vuejs/apollo/pull/1153
8
+ // Track removing this workaround in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/3152
11
9
  defaultHeaderLevel: () => this.headerLevel,
12
- accordionSetId: () => this.autoCollapse && accordionId,
10
+ autoCollapse: () => this.autoCollapse,
13
11
  };
14
12
  },
15
13
  props: {
@@ -1,21 +1,18 @@
1
1
  <script>
2
2
  import uniqueId from 'lodash/uniqueId';
3
- import { BCollapse } from '../../../vendor/bootstrap-vue/src/components/collapse/collapse';
3
+ import GlCollapse from '../collapse/collapse.vue';
4
4
  import GlAnimatedChevronRightDownIcon from '../animated_icon/animated_chevron_right_down_icon.vue';
5
- import { GlCollapseToggleDirective } from '../../../directives/collapse_toggle';
6
5
  import GlButton from '../button/button.vue';
6
+ import { COLLAPSE_EVENT } from './constants';
7
7
 
8
8
  export default {
9
9
  name: 'GlAccordionItem',
10
10
  components: {
11
- BCollapse,
11
+ GlCollapse,
12
12
  GlButton,
13
13
  GlAnimatedChevronRightDownIcon,
14
14
  },
15
- directives: {
16
- GlCollapseToggle: GlCollapseToggleDirective,
17
- },
18
- inject: ['accordionSetId', 'defaultHeaderLevel'],
15
+ inject: ['defaultHeaderLevel', 'autoCollapse'],
19
16
  inheritAttrs: false,
20
17
  model: {
21
18
  prop: 'visible',
@@ -68,7 +65,7 @@ export default {
68
65
  data() {
69
66
  return {
70
67
  accordionItemId: uniqueId('accordion-item-'),
71
- isVisible: this.visible,
68
+ localVisible: this.visible,
72
69
  };
73
70
  },
74
71
  computed: {
@@ -76,21 +73,54 @@ export default {
76
73
  const level = this.headerLevel || this.defaultHeaderLevel();
77
74
  return `h${level}`;
78
75
  },
79
- accordion() {
80
- return this.accordionSetId() || undefined;
81
- },
82
76
  buttonTitle() {
83
- return this.isVisible && this.titleVisible ? this.titleVisible : this.title;
77
+ return this.localVisible && this.titleVisible ? this.titleVisible : this.title;
84
78
  },
85
79
  },
80
+
86
81
  watch: {
87
- isVisible: {
88
- immediate: true,
89
- handler(isVisible) {
90
- this.$emit('input', isVisible);
82
+ visible: {
83
+ handler(newVisible) {
84
+ this.localVisible = newVisible;
85
+
86
+ this.checkAndCollapseSiblingAccordionItems(newVisible);
91
87
  },
92
88
  },
93
89
  },
90
+ created() {
91
+ this.$emit('input', this.localVisible);
92
+ },
93
+ mounted() {
94
+ this.$parent.$el.addEventListener(COLLAPSE_EVENT, this.onParentCollapse);
95
+ },
96
+ beforeDestroy() {
97
+ this.$parent.$el.removeEventListener(COLLAPSE_EVENT, this.onParentCollapse);
98
+ },
99
+ methods: {
100
+ onParentCollapse({ detail: accordionItemId }) {
101
+ if (accordionItemId === this.accordionItemId) {
102
+ return;
103
+ }
104
+
105
+ this.$emit('input', false);
106
+ this.localVisible = false;
107
+ },
108
+ onButtonClick() {
109
+ const newLocalVisible = !this.localVisible;
110
+
111
+ this.$emit('input', newLocalVisible);
112
+ this.localVisible = newLocalVisible;
113
+
114
+ this.checkAndCollapseSiblingAccordionItems(newLocalVisible);
115
+ },
116
+ checkAndCollapseSiblingAccordionItems(newVisible) {
117
+ if (this.autoCollapse() && newVisible) {
118
+ this.$parent.$el.dispatchEvent(
119
+ new CustomEvent(COLLAPSE_EVENT, { detail: this.accordionItemId })
120
+ );
121
+ }
122
+ },
123
+ },
94
124
  };
95
125
  </script>
96
126
 
@@ -98,24 +128,25 @@ export default {
98
128
  <div class="gl-accordion-item">
99
129
  <component :is="headerComponent" class="gl-accordion-item-header" :class="headerClass">
100
130
  <gl-button
101
- v-gl-collapse-toggle="accordionItemId"
102
131
  variant="link"
103
132
  button-text-classes="gl-flex"
133
+ :aria-expanded="localVisible ? 'true' : 'false'"
134
+ :aria-controls="accordionItemId"
135
+ @click="onButtonClick"
104
136
  >
105
- <gl-animated-chevron-right-down-icon :is-on="isVisible" />
137
+ <gl-animated-chevron-right-down-icon :is-on="localVisible" />
106
138
  {{ buttonTitle }}
107
139
  </gl-button>
108
140
  </component>
109
- <b-collapse
141
+ <gl-collapse
110
142
  :id="accordionItemId"
111
- v-model="isVisible"
112
- :visible="isVisible"
113
- :accordion="accordion"
114
- class="gl-mt-3 gl-text-base"
143
+ v-model="localVisible"
115
144
  :data-testid="`accordion-item-collapse-${accordionItemId}`"
116
145
  >
117
- <!-- @slot Item content -->
118
- <slot></slot>
119
- </b-collapse>
146
+ <div class="gl-mt-3 gl-text-base">
147
+ <!-- @slot Item content -->
148
+ <slot></slot>
149
+ </div>
150
+ </gl-collapse>
120
151
  </div>
121
152
  </template>
@@ -0,0 +1 @@
1
+ export const COLLAPSE_EVENT = 'collapse';
@@ -2,6 +2,7 @@
2
2
  <script>
3
3
  import isString from 'lodash/isString';
4
4
  import Pikaday from 'pikaday';
5
+ import { defaultConfig } from '../../../config';
5
6
  import { defaultDateFormat, datepickerWidthOptionsMap } from '../../../utils/constants';
6
7
  import { areDatesEqual } from '../../../utils/datetime_utility';
7
8
  import GlButton from '../button/button.vue';
@@ -120,7 +121,7 @@ export default {
120
121
  firstDay: {
121
122
  type: Number,
122
123
  required: false,
123
- default: 0,
124
+ default: () => defaultConfig.firstDayOfWeek || 0, // Defaults to 0 (Sunday)
124
125
  },
125
126
  ariaLabel: {
126
127
  type: String,
@@ -28,6 +28,7 @@ export default {
28
28
  directives: {
29
29
  SafeLink: SafeLinkDirective,
30
30
  },
31
+ inheritAttrs: false,
31
32
  props: {
32
33
  /**
33
34
  * Denotes the target URL of the link for standard links.
@@ -202,13 +203,22 @@ export default {
202
203
  return fallback;
203
204
  },
204
205
  computedProps() {
206
+ const baseRouterLinkProps = {
207
+ to: this.to,
208
+ activeClass: this.activeClass,
209
+ exactActiveClass: this.exactActiveClass,
210
+ replace: this.replace,
211
+ ...(isBoolean(this.prefetch) ? { prefetch: this.prefetch } : {}),
212
+ };
213
+
205
214
  if (this.isRouterLink) {
215
+ if (this.isVue3RouterLink) {
216
+ return baseRouterLinkProps;
217
+ }
218
+
206
219
  return {
207
- to: this.to,
208
- activeClass: this.activeClass,
209
- exactActiveClass: this.exactActiveClass,
210
- replace: this.replace,
211
- ...(isBoolean(this.prefetch) ? { prefetch: this.prefetch } : {}),
220
+ ...baseRouterLinkProps,
221
+ ...this.$attrs,
212
222
  };
213
223
  }
214
224
 
@@ -218,6 +228,7 @@ export default {
218
228
  rel: this.rel,
219
229
  target: this.target,
220
230
  href: this.computedHref,
231
+ ...this.$attrs,
221
232
  };
222
233
  },
223
234
  computedListeners() {
@@ -306,6 +317,7 @@ export default {
306
317
  v-safe-link:[safeLinkConfig]
307
318
  :class="[computedClass, { [activeClass]: isActive, [exactActiveClass]: isExactActive }]"
308
319
  :href="routerLinkHref"
320
+ v-bind="$attrs"
309
321
  v-on="computedListeners"
310
322
  @click="onClick($event, navigate)"
311
323
  >
package/src/config.js CHANGED
@@ -35,6 +35,10 @@ try {
35
35
 
36
36
  export const i18n = translationKeys;
37
37
 
38
+ export const defaultConfig = {
39
+ firstDayOfWeek: 0, // Defaults to 0 (Sunday)
40
+ };
41
+
38
42
  let configured = false;
39
43
 
40
44
  /**
@@ -43,8 +47,9 @@ let configured = false;
43
47
  * @typedef {object} GitLabUIConfiguration
44
48
  * @template TValue=string
45
49
  * @property {undefined | Object} translations Generic translations for component labels to fall back to.
50
+ * @property {undefined | Number} firstDayOfWeek Configured first day of the week, from 0 (Sunday) to 6 (Saturday).
46
51
  */
47
- const setConfigs = ({ translations } = {}) => {
52
+ const setConfigs = ({ translations, firstDayOfWeek } = {}) => {
48
53
  if (configured) {
49
54
  if (process.env.NODE_ENV === 'development') {
50
55
  throw new Error('GitLab UI can only be configured once!');
@@ -61,6 +66,10 @@ const setConfigs = ({ translations } = {}) => {
61
66
  },
62
67
  });
63
68
 
69
+ if (typeof firstDayOfWeek === 'number' && firstDayOfWeek >= 0 && firstDayOfWeek <= 6) {
70
+ defaultConfig.firstDayOfWeek = firstDayOfWeek;
71
+ }
72
+
64
73
  if (typeof translations === 'object') {
65
74
  if (process.env.NODE_ENV === 'development') {
66
75
  const undefinedTranslationKeys = Object.keys(i18n).reduce((acc, current) => {