@gitlab/ui 130.2.0 → 131.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.
Files changed (29) hide show
  1. package/dist/components/base/toast/index.js +66 -0
  2. package/dist/components/base/toast/toast.js +117 -89
  3. package/dist/components/base/toast/toaster.js +87 -0
  4. package/dist/components/charts/single_stat/single_stat.js +13 -1
  5. package/dist/components/index.js +1 -1
  6. package/dist/index.css +2 -2
  7. package/dist/index.css.map +1 -1
  8. package/dist/tailwind.css +1 -1
  9. package/dist/tailwind.css.map +1 -1
  10. package/package.json +1 -1
  11. package/src/components/base/toast/index.js +66 -0
  12. package/src/components/base/toast/toast.scss +31 -5
  13. package/src/components/base/toast/toast.vue +131 -0
  14. package/src/components/base/toast/toaster.vue +70 -0
  15. package/src/components/charts/single_stat/single_stat.vue +31 -3
  16. package/src/components/index.js +1 -1
  17. package/src/scss/bootstrap_vue.scss +0 -1
  18. package/dist/vendor/bootstrap-vue/src/components/toast/helpers/bv-toast.js +0 -234
  19. package/dist/vendor/bootstrap-vue/src/components/toast/index.js +0 -19
  20. package/dist/vendor/bootstrap-vue/src/components/toast/toast.js +0 -407
  21. package/dist/vendor/bootstrap-vue/src/components/toast/toaster.js +0 -142
  22. package/src/components/base/toast/toast.js +0 -102
  23. package/src/vendor/bootstrap-vue/src/components/toast/_toast.scss +0 -77
  24. package/src/vendor/bootstrap-vue/src/components/toast/_toaster.scss +0 -108
  25. package/src/vendor/bootstrap-vue/src/components/toast/helpers/bv-toast.js +0 -231
  26. package/src/vendor/bootstrap-vue/src/components/toast/index.js +0 -12
  27. package/src/vendor/bootstrap-vue/src/components/toast/index.scss +0 -2
  28. package/src/vendor/bootstrap-vue/src/components/toast/toast.js +0 -439
  29. package/src/vendor/bootstrap-vue/src/components/toast/toaster.js +0 -136
@@ -0,0 +1,66 @@
1
+ import Vue from 'vue';
2
+ import { createNewChildComponent } from '../../../vendor/bootstrap-vue/src/utils/create-new-child-component';
3
+ import GlToaster from './toaster';
4
+
5
+ /* eslint-disable import/no-default-export */
6
+ let toastsCount = 0;
7
+ let toasterInstance = null;
8
+ function ensureToaster(vm) {
9
+ if (toasterInstance) {
10
+ const portalTarget = document.getElementById('gl-toaster');
11
+ if (portalTarget && document.body.contains(portalTarget)) {
12
+ return toasterInstance;
13
+ }
14
+ toasterInstance.$destroy();
15
+ toasterInstance = null;
16
+ }
17
+ const ToasterComponent = Vue.extend(GlToaster);
18
+ toasterInstance = createNewChildComponent(vm, ToasterComponent);
19
+ toasterInstance.$mount(document.createElement('div'));
20
+ return toasterInstance;
21
+ }
22
+ function showToast(message) {
23
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
24
+ const toaster = ensureToaster(this);
25
+
26
+ // eslint-disable-next-line @gitlab/tailwind-no-interpolation -- Not a CSS utility
27
+ const id = `gl-toast-${toastsCount}`;
28
+ toastsCount += 1;
29
+ const hide = () => toaster.hideToast(id);
30
+ const toast = {
31
+ id,
32
+ hide
33
+ };
34
+ const autoHideDelay = !Number.isNaN(options === null || options === void 0 ? void 0 : options.autoHideDelay) ? options.autoHideDelay : undefined;
35
+ toaster.addToast({
36
+ id,
37
+ message,
38
+ action: options.action || null,
39
+ autoHideDelay,
40
+ onComplete: options.onComplete || null
41
+ });
42
+ return toast;
43
+ }
44
+
45
+ /**
46
+ * Note: This is not a typical Vue component and needs to be registered before instantiating a Vue app.
47
+ * Once registered, the toast will be globally available throughout your app.
48
+ *
49
+ * See https://design.gitlab.com/storybook for detailed documentation.
50
+ */
51
+ var index = {
52
+ install(V) {
53
+ V.mixin({
54
+ beforeCreate() {
55
+ if (this.$toast) {
56
+ return;
57
+ }
58
+ this.$toast = {
59
+ show: showToast.bind(this)
60
+ };
61
+ }
62
+ });
63
+ }
64
+ };
65
+
66
+ export { index as default };
@@ -1,97 +1,125 @@
1
- import { isFunction } from 'lodash-es';
2
- import { ToastPlugin } from '../../../vendor/bootstrap-vue/src/components/toast/index';
3
1
  import CloseButton from '../../shared_components/close_button/close_button';
2
+ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
4
3
 
5
- /* eslint-disable import/no-default-export */
6
- const DEFAULT_OPTIONS = {
7
- autoHideDelay: 5000,
8
- toastClass: 'gl-toast',
9
- isStatus: true,
10
- toaster: 'b-toaster-bottom-left',
11
- appendToast: true
12
- };
13
- let toastsCount = 0;
14
- function renderTitle(toast, options) {
15
- return h => {
16
- const nodes = [h(CloseButton, {
17
- class: ['gl-toast-close-button'],
18
- on: {
19
- click: toast.hide
20
- }
21
- })];
22
- if (options.action) {
23
- const {
24
- onClick,
25
- text,
26
- href
27
- } = options.action;
28
- nodes.unshift(h('a', {
29
- attrs: {
30
- role: href ? undefined : 'button',
31
- href
32
- },
33
- class: ['gl-toast-action'],
34
- on: {
35
- click: e => onClick(e, toast)
36
- }
37
- }, text));
4
+ const MIN_DURATION = 1000;
5
+ const DEFAULT_AUTO_HIDE_DELAY = 5000;
6
+ const hasAnimateSupport = typeof Element !== 'undefined' && Boolean(Element.prototype.animate);
7
+ var script = {
8
+ name: 'GlToast',
9
+ components: {
10
+ CloseButton
11
+ },
12
+ props: {
13
+ toastId: {
14
+ type: String,
15
+ required: true
16
+ },
17
+ message: {
18
+ type: String,
19
+ required: true
20
+ },
21
+ action: {
22
+ type: Object,
23
+ required: false,
24
+ default: null
25
+ },
26
+ autoHideDelay: {
27
+ type: Number,
28
+ required: false,
29
+ default: DEFAULT_AUTO_HIDE_DELAY
38
30
  }
39
- return nodes;
40
- };
41
- }
42
- function showToast(message) {
43
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
44
- // eslint-disable-next-line @gitlab/tailwind-no-interpolation -- Not a CSS utility
45
- const id = `gl-toast-${toastsCount}`;
46
- toastsCount += 1;
47
- const hide = () => {
48
- this.$bvToast.hide(id);
49
- };
50
- const toast = {
51
- id,
52
- hide
53
- };
54
- if (isFunction(options.onComplete)) {
55
- const toastHiddenCallback = e => {
56
- if (e.componentId === id) {
57
- this.$root.$off('bv::toast:hidden', toastHiddenCallback);
58
- options.onComplete(e);
59
- }
31
+ },
32
+ data() {
33
+ return {
34
+ visible: true
60
35
  };
61
- this.$root.$on('bv::toast:hidden', toastHiddenCallback);
62
- }
63
- const updatedAutoHideDelay = !Number.isNaN(options === null || options === void 0 ? void 0 : options.autoHideDelay) ? {
64
- autoHideDelay: options.autoHideDelay
65
- } : null;
66
- this.$bvToast.toast(message, {
67
- ...DEFAULT_OPTIONS,
68
- ...updatedAutoHideDelay,
69
- id,
70
- title: renderTitle(toast, options)
71
- });
72
- return toast;
73
- }
74
-
75
- /**
76
- * Note: This is not a typical Vue component and needs to be registered before instantiating a Vue app.
77
- * Once registered, the toast will be globally available throughout your app.
78
- *
79
- * See https://design.gitlab.com/storybook for detailed documentation.
80
- */
81
- var toast = {
82
- install(Vue) {
83
- Vue.use(ToastPlugin);
84
- Vue.mixin({
85
- beforeCreate() {
86
- if (this.$toast) {
87
- return;
88
- }
89
- this.$toast = {
90
- show: showToast.bind(this)
91
- };
36
+ },
37
+ computed: {
38
+ effectiveDelay() {
39
+ return Math.max(this.autoHideDelay, MIN_DURATION);
40
+ }
41
+ },
42
+ created() {
43
+ this.useCssTransition = hasAnimateSupport;
44
+ this.dismissTimer = null;
45
+ this.deadline = 0;
46
+ this.timeRemaining = this.effectiveDelay;
47
+ this.isHiding = false;
48
+ },
49
+ beforeDestroy() {
50
+ clearTimeout(this.dismissTimer);
51
+ },
52
+ methods: {
53
+ startDismissTimer() {
54
+ clearTimeout(this.dismissTimer);
55
+ this.deadline = Date.now() + this.timeRemaining;
56
+ this.dismissTimer = setTimeout(() => this.hide(), this.timeRemaining);
57
+ },
58
+ onPause() {
59
+ if (!this.dismissTimer) return;
60
+ clearTimeout(this.dismissTimer);
61
+ this.dismissTimer = null;
62
+ this.timeRemaining = Math.max(this.deadline - Date.now(), MIN_DURATION);
63
+ },
64
+ onResume() {
65
+ if (!this.timeRemaining || this.dismissTimer) return;
66
+ this.startDismissTimer();
67
+ },
68
+ hide() {
69
+ if (this.isHiding) return;
70
+ this.isHiding = true;
71
+ clearTimeout(this.dismissTimer);
72
+ this.dismissTimer = null;
73
+ this.visible = false;
74
+ },
75
+ onAfterLeave() {
76
+ this.$emit('hidden', this.toastId);
77
+ },
78
+ onActionClick(e) {
79
+ if (this.action && this.action.onClick) {
80
+ this.action.onClick(e, {
81
+ id: this.toastId,
82
+ hide: () => this.hide()
83
+ });
92
84
  }
93
- });
85
+ }
94
86
  }
95
87
  };
96
88
 
97
- export { toast as default };
89
+ /* script */
90
+ const __vue_script__ = script;
91
+
92
+ /* template */
93
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"b-toast b-toast-append",attrs:{"id":(_vm.toastId + "_toast_outer"),"role":"status","aria-live":"polite","aria-atomic":"true"}},[_c('transition',{attrs:{"enter-active-class":"fade","enter-to-class":"show","leave-class":"show","leave-active-class":"fade","appear":"","appear-active-class":"fade","appear-to-class":"show","css":_vm.useCssTransition},on:{"after-appear":_vm.startDismissTimer,"after-leave":_vm.onAfterLeave}},[(_vm.visible)?_c('div',{staticClass:"toast gl-toast",attrs:{"id":_vm.toastId,"tabindex":"0"},on:{"mouseenter":_vm.onPause,"mouseleave":_vm.onResume}},[_c('div',{staticClass:"toast-body"},[_vm._v(_vm._s(_vm.message))]),_vm._v(" "),_c('header',{staticClass:"toast-header"},[(_vm.action)?_c('a',{staticClass:"gl-toast-action",attrs:{"role":_vm.action.href ? undefined : 'button',"href":_vm.action.href},on:{"click":_vm.onActionClick}},[_vm._v(_vm._s(_vm.action.text))]):_vm._e(),_vm._v(" "),_c('close-button',{staticClass:"gl-toast-close-button",on:{"click":_vm.hide}})],1)]):_vm._e()])],1)};
94
+ var __vue_staticRenderFns__ = [];
95
+
96
+ /* style */
97
+ const __vue_inject_styles__ = undefined;
98
+ /* scoped */
99
+ const __vue_scope_id__ = undefined;
100
+ /* module identifier */
101
+ const __vue_module_identifier__ = undefined;
102
+ /* functional template */
103
+ const __vue_is_functional_template__ = false;
104
+ /* style inject */
105
+
106
+ /* style inject SSR */
107
+
108
+ /* style inject shadow dom */
109
+
110
+
111
+
112
+ const __vue_component__ = /*#__PURE__*/__vue_normalize__(
113
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
114
+ __vue_inject_styles__,
115
+ __vue_script__,
116
+ __vue_scope_id__,
117
+ __vue_is_functional_template__,
118
+ __vue_module_identifier__,
119
+ false,
120
+ undefined,
121
+ undefined,
122
+ undefined
123
+ );
124
+
125
+ export { __vue_component__ as default };
@@ -0,0 +1,87 @@
1
+ import { MountingPortal } from 'portal-vue';
2
+ import GlToast from './toast';
3
+ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
4
+
5
+ const hasViewTransitions = typeof document !== 'undefined' && typeof document.startViewTransition === 'function';
6
+ var script = {
7
+ name: 'GlToaster',
8
+ components: {
9
+ MountingPortal,
10
+ GlToast
11
+ },
12
+ expose: ['addToast', 'hideToast', 'removeToast'],
13
+ data() {
14
+ return {
15
+ toasts: []
16
+ };
17
+ },
18
+ methods: {
19
+ addToast(config) {
20
+ const add = () => this.toasts.push(config);
21
+ if (hasViewTransitions && this.toasts.length > 0) {
22
+ document.startViewTransition(add);
23
+ } else {
24
+ add();
25
+ }
26
+ },
27
+ hideToast(id) {
28
+ const refs = this.$refs.toastRefs;
29
+ if (!refs) return;
30
+ const toastComponents = Array.isArray(refs) ? refs : [refs];
31
+ const component = toastComponents.find(c => c.toastId === id);
32
+ if (component) {
33
+ component.hide();
34
+ }
35
+ },
36
+ removeToast(id) {
37
+ const idx = this.toasts.findIndex(t => t.id === id);
38
+ if (idx !== -1) {
39
+ const toast = this.toasts[idx];
40
+ this.toasts.splice(idx, 1);
41
+ if (toast.onComplete) {
42
+ toast.onComplete({
43
+ componentId: id
44
+ });
45
+ }
46
+ }
47
+ }
48
+ }
49
+ };
50
+
51
+ /* script */
52
+ const __vue_script__ = script;
53
+
54
+ /* template */
55
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('mounting-portal',{attrs:{"mount-to":"body","append":""}},[_c('div',{staticClass:"b-toaster b-toaster-bottom-left",attrs:{"id":"gl-toaster"}},[_c('div',{staticClass:"b-toaster-slot"},_vm._l((_vm.toasts),function(toast){return _c('gl-toast',{key:toast.id,ref:"toastRefs",refInFor:true,attrs:{"toast-id":toast.id,"message":toast.message,"action":toast.action,"auto-hide-delay":toast.autoHideDelay},on:{"hidden":_vm.removeToast}})}),1)])])};
56
+ var __vue_staticRenderFns__ = [];
57
+
58
+ /* style */
59
+ const __vue_inject_styles__ = undefined;
60
+ /* scoped */
61
+ const __vue_scope_id__ = undefined;
62
+ /* module identifier */
63
+ const __vue_module_identifier__ = undefined;
64
+ /* functional template */
65
+ const __vue_is_functional_template__ = false;
66
+ /* style inject */
67
+
68
+ /* style inject SSR */
69
+
70
+ /* style inject shadow dom */
71
+
72
+
73
+
74
+ const __vue_component__ = /*#__PURE__*/__vue_normalize__(
75
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
76
+ __vue_inject_styles__,
77
+ __vue_script__,
78
+ __vue_scope_id__,
79
+ __vue_is_functional_template__,
80
+ __vue_module_identifier__,
81
+ false,
82
+ undefined,
83
+ undefined,
84
+ undefined
85
+ );
86
+
87
+ export { __vue_component__ as default };
@@ -3,6 +3,7 @@ import GlBadge from '../../base/badge/badge';
3
3
  import GlIcon from '../../base/icon/icon';
4
4
  import GlAnimatedNumber from '../../utilities/animated_number/animated_number';
5
5
  import { formatNumberToLocale } from '../../../utils/number_utils';
6
+ import { GlTooltipDirective } from '../../../directives/tooltip/tooltip';
6
7
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
7
8
 
8
9
  var script = {
@@ -12,6 +13,9 @@ var script = {
12
13
  GlBadge,
13
14
  GlAnimatedNumber
14
15
  },
16
+ directives: {
17
+ GlTooltip: GlTooltipDirective
18
+ },
15
19
  props: {
16
20
  title: {
17
21
  type: String,
@@ -63,6 +67,14 @@ var script = {
63
67
  required: false,
64
68
  default: null
65
69
  },
70
+ /**
71
+ * Tooltip text for the meta badge. When provided, the badge is wrapped in a button to ensure keyboard accessibility.
72
+ */
73
+ metaTooltip: {
74
+ type: String,
75
+ required: false,
76
+ default: ''
77
+ },
66
78
  shouldAnimate: {
67
79
  type: Boolean,
68
80
  required: false,
@@ -117,7 +129,7 @@ var script = {
117
129
  const __vue_script__ = script;
118
130
 
119
131
  /* template */
120
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',_vm._g(_vm._b({staticClass:"gl-single-stat gl-flex gl-flex-col gl-p-2"},'div',_vm.$attrs,false),_vm.$listeners),[_c('div',{staticClass:"gl-mb-2 gl-flex gl-items-center gl-text-heading"},[(_vm.showTitleIcon)?_c('gl-icon',{class:['gl-mr-2', _vm.titleIconClass],attrs:{"name":_vm.titleIcon,"data-testid":"title-icon"}}):_vm._e(),_vm._v(" "),_c('span',{staticClass:"gl-text-base gl-font-normal",attrs:{"data-testid":"title-text"}},[_vm._v(_vm._s(_vm.title))])],1),_vm._v(" "),_c('div',{staticClass:"gl-single-stat-content gl-flex gl-items-baseline gl-font-bold gl-text-strong"},[_c('span',{staticClass:"gl-single-stat-number gl-leading-1",class:{ 'gl-mr-2': !_vm.unit },attrs:{"data-testid":"displayValue"}},[(_vm.canAnimate)?_c('gl-animated-number',{attrs:{"number":Number(_vm.value),"decimal-places":_vm.animationDecimalPlaces,"use-delimiters":_vm.useDelimiters},on:{"animating":function($event){return _vm.setHideUnits(true)},"animated":function($event){return _vm.setHideUnits(false)}}}):_c('span',{attrs:{"data-testid":"non-animated-value"}},[_vm._v(_vm._s(_vm.statValue))])],1),_vm._v(" "),(_vm.unit)?_c('span',{staticClass:"gl-mx-2 gl-text-sm gl-opacity-10 gl-transition-all",class:{ '!gl-opacity-0': _vm.hideUnits },attrs:{"data-testid":"unit"}},[_vm._v(_vm._s(_vm.unit))]):_vm._e(),_vm._v(" "),(_vm.showMetaIcon)?_c('gl-icon',{attrs:{"variant":_vm.iconVariant,"name":_vm.metaIcon,"data-testid":"meta-icon"}}):_vm._e(),_vm._v(" "),(_vm.showBadge)?_c('gl-badge',{attrs:{"variant":_vm.variant,"icon":_vm.metaIcon,"data-testid":"meta-badge"}},[_vm._v(_vm._s(_vm.metaText))]):_vm._e()],1)])};
132
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',_vm._g(_vm._b({staticClass:"gl-single-stat gl-flex gl-flex-col gl-p-2"},'div',_vm.$attrs,false),_vm.$listeners),[_c('div',{staticClass:"gl-mb-2 gl-flex gl-items-center gl-text-heading"},[(_vm.showTitleIcon)?_c('gl-icon',{class:['gl-mr-2', _vm.titleIconClass],attrs:{"name":_vm.titleIcon,"data-testid":"title-icon"}}):_vm._e(),_vm._v(" "),_c('span',{staticClass:"gl-text-base gl-font-normal",attrs:{"data-testid":"title-text"}},[_vm._v(_vm._s(_vm.title))])],1),_vm._v(" "),_c('div',{staticClass:"gl-single-stat-content gl-flex gl-items-baseline gl-font-bold gl-text-strong"},[_c('span',{staticClass:"gl-single-stat-number gl-leading-1",class:{ 'gl-mr-2': !_vm.unit },attrs:{"data-testid":"displayValue"}},[(_vm.canAnimate)?_c('gl-animated-number',{attrs:{"number":Number(_vm.value),"decimal-places":_vm.animationDecimalPlaces,"use-delimiters":_vm.useDelimiters},on:{"animating":function($event){return _vm.setHideUnits(true)},"animated":function($event){return _vm.setHideUnits(false)}}}):_c('span',{attrs:{"data-testid":"non-animated-value"}},[_vm._v(_vm._s(_vm.statValue))])],1),_vm._v(" "),(_vm.unit)?_c('span',{staticClass:"gl-mx-2 gl-text-sm gl-opacity-10 gl-transition-all",class:{ '!gl-opacity-0': _vm.hideUnits },attrs:{"data-testid":"unit"}},[_vm._v(_vm._s(_vm.unit))]):_vm._e(),_vm._v(" "),(_vm.showMetaIcon)?_c('gl-icon',{attrs:{"variant":_vm.iconVariant,"name":_vm.metaIcon,"data-testid":"meta-icon"}}):_vm._e(),_vm._v(" "),(_vm.showBadge && _vm.metaTooltip)?_c('button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip.viewport",modifiers:{"viewport":true}}],staticClass:"!gl-cursor-default gl-border-0 gl-bg-transparent gl-p-0 gl-leading-0",attrs:{"type":"button","title":_vm.metaTooltip,"data-testid":"meta-badge-button"}},[_c('gl-badge',{attrs:{"variant":_vm.variant,"icon":_vm.metaIcon,"data-testid":"meta-badge"}},[_vm._v(_vm._s(_vm.metaText))])],1):(_vm.showBadge)?_c('gl-badge',{attrs:{"variant":_vm.variant,"icon":_vm.metaIcon,"data-testid":"meta-badge"}},[_vm._v(_vm._s(_vm.metaText))]):_vm._e()],1)])};
121
133
  var __vue_staticRenderFns__ = [];
122
134
 
123
135
  /* style */
@@ -32,7 +32,7 @@ export { default as GlBadge } from './base/badge/badge';
32
32
  export { default as GlBanner } from './base/banner/banner';
33
33
  export { default as GlButton } from './base/button/button';
34
34
  export { default as GlTooltip } from './base/tooltip/tooltip';
35
- export { default as GlToast } from './base/toast/toast';
35
+ export { default as GlToast } from './base/toast';
36
36
  export { default as GlDashboardSkeleton } from './regions/dashboard_skeleton/dashboard_skeleton';
37
37
  export { default as GlEmptyState } from './regions/empty_state/empty_state';
38
38
  export { default as GlForm } from './base/form/form';