@gitlab/ui 115.0.0 → 115.1.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/bin/migrate_custom_utils_to_tw.bundled.mjs +172489 -139144
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +15 -3
- package/dist/components/base/new_dropdowns/constants.js +5 -2
- package/dist/components/dashboards/dashboard_layout/grid_layout/grid_layout.js +286 -0
- package/dist/components/dashboards/mock_data.js +49 -0
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tailwind.css.map +1 -1
- package/dist/tokens/docs/tokens-tailwind-docs.dark.json +7986 -0
- package/dist/tokens/docs/tokens-tailwind-docs.json +7986 -0
- package/dist/tokens/figma/constants.tokens.json +944 -236
- package/dist/tokens/figma/contextual.tokens.json +2721 -418
- package/dist/tokens/figma/deprecated.tokens.json +664 -8
- package/dist/tokens/figma/semantic.tokens.json +1130 -169
- package/dist/tokens/js/tokens.dark.js +1089 -1047
- package/dist/tokens/js/tokens.js +1078 -1047
- package/dist/tokens/json/tokens.dark.json +9267 -3
- package/dist/tokens/json/tokens.json +9267 -3
- package/dist/tokens/tailwind/tokens.cjs +76 -407
- package/package.json +22 -49
- package/src/components/base/accordion/accordion_item.vue +1 -1
- package/src/components/base/avatar/avatar.vue +1 -1
- package/src/components/base/button/button.vue +1 -1
- package/src/components/base/dropdown/dropdown.vue +3 -1
- package/src/components/base/filtered_search/filtered_search.vue +1 -1
- package/src/components/base/filtered_search/filtered_search_suggestion_list.vue +1 -1
- package/src/components/base/filtered_search/filtered_search_token.vue +1 -1
- package/src/components/base/filtered_search/filtered_search_token_segment.vue +3 -3
- package/src/components/base/form/form_checkbox_tree/models/tree.js +1 -1
- package/src/components/base/form/form_date/form_date.vue +1 -1
- package/src/components/base/form/form_input/form_input.vue +1 -1
- package/src/components/base/form/form_select/form_select.vue +1 -1
- package/src/components/base/modal/modal.vue +2 -2
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +23 -6
- package/src/components/base/new_dropdowns/constants.js +4 -1
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.md +1 -2
- package/src/components/base/new_dropdowns/listbox/listbox.vue +7 -7
- package/src/components/base/pagination/pagination.vue +2 -2
- package/src/components/base/path/path.vue +1 -1
- package/src/components/base/skeleton_loader/skeleton_loader.vue +9 -9
- package/src/components/base/table/table.md +1 -2
- package/src/components/base/table_lite/table_lite.md +1 -1
- package/src/components/base/tabs/tabs/tabs.vue +1 -1
- package/src/components/base/toast/toast.js +2 -2
- package/src/components/base/token_selector/token_container.vue +1 -1
- package/src/components/base/token_selector/token_selector.vue +2 -2
- package/src/components/base/token_selector/token_selector_dropdown.vue +1 -1
- package/src/components/charts/area/area.vue +3 -3
- package/src/components/charts/bar/bar.vue +2 -2
- package/src/components/charts/column/column.vue +2 -2
- package/src/components/charts/discrete_scatter/discrete_scatter.vue +2 -2
- package/src/components/charts/gauge/gauge.vue +1 -1
- package/src/components/charts/heatmap/heatmap.vue +2 -2
- package/src/components/charts/heatmap/index.js +1 -0
- package/src/components/charts/legend/legend.vue +1 -1
- package/src/components/charts/line/line.vue +3 -3
- package/src/components/charts/sparkline/sparkline.vue +1 -1
- package/src/components/charts/stacked_column/stacked_column.vue +1 -1
- package/src/components/dashboards/dashboard_layout/grid_layout/grid_layout.scss +1 -0
- package/src/components/dashboards/dashboard_layout/grid_layout/grid_layout.vue +247 -0
- package/src/components/dashboards/mock_data.js +40 -0
- package/src/components/mixins/tooltip_mixin.js +1 -1
- package/src/components/utilities/intersection_observer/intersection_observer.vue +1 -1
- package/src/components/utilities/intersperse/intersperse.vue +2 -2
- package/src/components/utilities/sprintf/sprintf.md +1 -1
- package/src/components/utilities/sprintf/sprintf.vue +1 -1
- package/src/components/utilities/truncate/truncate.vue +2 -2
- package/src/config.js +1 -1
- package/src/directives/outside/outside.js +4 -4
- package/src/directives/tooltip/tooltip.js +1 -1
- package/src/scss/components.scss +1 -0
- package/src/tokens/build/docs/tokens-tailwind-docs.dark.json +7986 -0
- package/src/tokens/build/docs/tokens-tailwind-docs.json +7986 -0
- package/src/tokens/build/figma/constants.tokens.json +944 -236
- package/src/tokens/build/figma/contextual.tokens.json +2721 -418
- package/src/tokens/build/figma/deprecated.tokens.json +664 -8
- package/src/tokens/build/figma/semantic.tokens.json +1130 -169
- package/src/tokens/build/json/tokens.dark.json +9267 -3
- package/src/tokens/build/json/tokens.json +9267 -3
- package/src/tokens/constant/color.alpha.tokens.json +60 -15
- package/src/tokens/constant/color.tokens.json +844 -211
- package/src/tokens/constant/line_height.tokens.json +40 -10
- package/src/tokens/contextual/alert.tokens.json +119 -19
- package/src/tokens/contextual/avatar.tokens.json +90 -14
- package/src/tokens/contextual/badge.tokens.json +728 -112
- package/src/tokens/contextual/banner.tokens.json +19 -3
- package/src/tokens/contextual/breadcrumb.tokens.json +6 -1
- package/src/tokens/contextual/broadcast.tokens.json +301 -81
- package/src/tokens/contextual/button.tokens.json +793 -120
- package/src/tokens/contextual/chart.tokens.json +42 -7
- package/src/tokens/contextual/datepicker.tokens.json +13 -2
- package/src/tokens/contextual/dropdown.tokens.json +142 -21
- package/src/tokens/contextual/filtered-search.tokens.json +42 -6
- package/src/tokens/contextual/illustration.tokens.json +195 -33
- package/src/tokens/contextual/label.tokens.json +81 -12
- package/src/tokens/contextual/link.tokens.json +26 -4
- package/src/tokens/contextual/progress-bar.tokens.json +35 -5
- package/src/tokens/contextual/skeleton-loader.tokens.json +12 -2
- package/src/tokens/contextual/spinner.tokens.json +24 -4
- package/src/tokens/contextual/table.tokens.json +14 -2
- package/src/tokens/contextual/tabs.tokens.json +7 -1
- package/src/tokens/contextual/toggle.tokens.json +54 -9
- package/src/tokens/contextual/token-selector.tokens.json +7 -1
- package/src/tokens/contextual/token.tokens.json +14 -2
- package/src/tokens/deprecated/deprecated.color.data_viz.tokens.json +165 -0
- package/src/tokens/deprecated/deprecated.color.theme.tokens.json +216 -0
- package/src/tokens/deprecated/deprecated.color.tokens.json +240 -0
- package/src/tokens/deprecated/deprecated.color.transparency.tokens.json +39 -0
- package/src/tokens/semantic/action.tokens.json +500 -75
- package/src/tokens/semantic/background.tokens.json +49 -7
- package/src/tokens/semantic/border.tokens.json +30 -5
- package/src/tokens/semantic/control.tokens.json +129 -20
- package/src/tokens/semantic/feedback.tokens.json +126 -19
- package/src/tokens/semantic/focus-ring.tokens.json +12 -2
- package/src/tokens/semantic/highlight.tokens.json +26 -4
- package/src/tokens/semantic/icon.tokens.json +63 -9
- package/src/tokens/semantic/shadow.tokens.json +6 -1
- package/src/tokens/semantic/status.tokens.json +120 -18
- package/src/tokens/semantic/text.tokens.json +69 -9
- package/src/tokens/tokens_tailwind_table.vue +1 -1
- package/src/utils/charts/config.js +7 -7
- package/src/utils/charts/utils.js +1 -1
- package/src/utils/use_mock_intersection_observer.js +1 -1
- package/src/utils/utils.js +1 -1
- package/tailwind.defaults.js +1 -1
- package/translations.js +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import uniqueId from 'lodash/uniqueId';
|
|
2
2
|
import { offset, autoPlacement, shift, arrow, size, autoUpdate, computePosition } from '@floating-ui/dom';
|
|
3
3
|
import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropdownPlacements, dropdownAllowedAutoPlacements } from '../../../../utils/constants';
|
|
4
|
-
import { POSITION_ABSOLUTE, POSITION_FIXED, GL_DROPDOWN_CONTENTS_CLASS, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, ENTER, SPACE, ARROW_DOWN, GL_DROPDOWN_FOCUS_CONTENT } from '../constants';
|
|
5
|
-
import { logWarning, isElementFocusable, isElementTabbable } from '../../../../utils/utils';
|
|
4
|
+
import { POSITION_ABSOLUTE, POSITION_FIXED, GL_DROPDOWN_CONTENTS_CLASS, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, KEY_CODE_ESCAPE, ENTER, SPACE, ARROW_DOWN, GL_DROPDOWN_FOCUS_CONTENT } from '../constants';
|
|
5
|
+
import { logWarning, isElementFocusable, isElementTabbable, stopEvent } from '../../../../utils/utils';
|
|
6
6
|
import { OutsideDirective } from '../../../../directives/outside/outside';
|
|
7
7
|
import GlButton from '../../button/button';
|
|
8
8
|
import GlIcon from '../../icon/icon';
|
|
@@ -461,11 +461,23 @@ var script = {
|
|
|
461
461
|
},
|
|
462
462
|
onKeydown(event) {
|
|
463
463
|
const {
|
|
464
|
+
keyCode,
|
|
464
465
|
code,
|
|
465
466
|
target: {
|
|
466
467
|
tagName
|
|
467
468
|
}
|
|
468
469
|
} = event;
|
|
470
|
+
|
|
471
|
+
// Use keyCode because @vue/test-utils doesn't correctly set the
|
|
472
|
+
// `code` and `key` KeyboardEvent properties. This is only needed in this case because:
|
|
473
|
+
// - We are not using the @keydown.esc template syntax, which under Vue 2 checks against `keyCode` anyway.
|
|
474
|
+
// - The `.trigger('keydown.esc')` shorthand @vue/test-utils provides is useful.
|
|
475
|
+
// See https://github.com/vuejs/vue-test-utils/issues/2096
|
|
476
|
+
if (keyCode === KEY_CODE_ESCAPE && this.visible) {
|
|
477
|
+
stopEvent(event);
|
|
478
|
+
this.close();
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
469
481
|
let toggleOnEnter = true;
|
|
470
482
|
let toggleOnSpace = true;
|
|
471
483
|
if (tagName === 'BUTTON') {
|
|
@@ -496,7 +508,7 @@ var script = {
|
|
|
496
508
|
const __vue_script__ = script;
|
|
497
509
|
|
|
498
510
|
/* template */
|
|
499
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"outside",rawName:"v-outside.click.focusin",value:(_vm.close),expression:"close",modifiers:{"click":true,"focusin":true}}],class:[_vm.$options.BASE_DROPDOWN_CLASS, { '!gl-block': _vm.block }]},[_c(_vm.toggleComponent,_vm._g(_vm._b({ref:"toggle",tag:"component",attrs:{"id":_vm.toggleId,"data-testid":"base-dropdown-toggle"}
|
|
511
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"outside",rawName:"v-outside.click.focusin",value:(_vm.close),expression:"close",modifiers:{"click":true,"focusin":true}}],class:[_vm.$options.BASE_DROPDOWN_CLASS, { '!gl-block': _vm.block }]},[_c(_vm.toggleComponent,_vm._g(_vm._b({ref:"toggle",tag:"component",attrs:{"id":_vm.toggleId,"data-testid":"base-dropdown-toggle"}},'component',_vm.toggleAttributes,false),_vm.toggleListeners),[_vm._t("toggle",function(){return [_c('span',{staticClass:"gl-new-dropdown-button-text",class:{ 'gl-sr-only': _vm.textSrOnly }},[_vm._v("\n "+_vm._s(_vm.toggleText)+"\n ")]),_vm._v(" "),(!_vm.noCaret)?_c('gl-icon',{staticClass:"gl-button-icon gl-new-dropdown-chevron",attrs:{"name":"chevron-down"}}):_vm._e()]})],2),_vm._v(" "),_c('div',{ref:"content",staticClass:"gl-new-dropdown-panel",class:_vm.panelClasses,attrs:{"id":_vm.baseDropdownId,"data-testid":"base-dropdown-menu"},on:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();$event.preventDefault();return _vm.closeAndFocus.apply(null, arguments)}}},[_c('div',{ref:"dropdownArrow",staticClass:"gl-new-dropdown-arrow"}),_vm._v(" "),_c('div',{staticClass:"gl-new-dropdown-inner"},[_vm._t("default",null,{"visible":_vm.visible})],2)])],1)};
|
|
500
512
|
var __vue_staticRenderFns__ = [];
|
|
501
513
|
|
|
502
514
|
/* style */
|
|
@@ -4,7 +4,7 @@ const GL_DROPDOWN_HIDDEN = 'hidden';
|
|
|
4
4
|
const GL_DROPDOWN_BEFORE_CLOSE = 'beforeClose';
|
|
5
5
|
const GL_DROPDOWN_FOCUS_CONTENT = 'focusContent';
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// KeyboardEvent.code values
|
|
8
8
|
const ARROW_DOWN = 'ArrowDown';
|
|
9
9
|
const ARROW_UP = 'ArrowUp';
|
|
10
10
|
const END = 'End';
|
|
@@ -12,10 +12,13 @@ const ENTER = 'Enter';
|
|
|
12
12
|
const HOME = 'Home';
|
|
13
13
|
const SPACE = 'Space';
|
|
14
14
|
|
|
15
|
+
// KeyboardEvent.keyCode values
|
|
16
|
+
const KEY_CODE_ESCAPE = 27;
|
|
17
|
+
|
|
15
18
|
// Positioning strategies
|
|
16
19
|
// https://floating-ui.com/docs/computePosition#strategy
|
|
17
20
|
const POSITION_ABSOLUTE = 'absolute';
|
|
18
21
|
const POSITION_FIXED = 'fixed';
|
|
19
22
|
const GL_DROPDOWN_CONTENTS_CLASS = 'gl-new-dropdown-contents';
|
|
20
23
|
|
|
21
|
-
export { ARROW_DOWN, ARROW_UP, END, ENTER, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_CONTENTS_CLASS, GL_DROPDOWN_FOCUS_CONTENT, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_SHOWN, HOME, POSITION_ABSOLUTE, POSITION_FIXED, SPACE };
|
|
24
|
+
export { ARROW_DOWN, ARROW_UP, END, ENTER, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_CONTENTS_CLASS, GL_DROPDOWN_FOCUS_CONTENT, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_SHOWN, HOME, KEY_CODE_ESCAPE, POSITION_ABSOLUTE, POSITION_FIXED, SPACE };
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { GridStack } from 'gridstack';
|
|
2
|
+
import pickBy from 'lodash/pickBy';
|
|
3
|
+
import { breakpoints } from '../../../../utils/breakpoints';
|
|
4
|
+
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
5
|
+
|
|
6
|
+
const CURSOR_GRABBING_CLASS = '!gl-cursor-grabbing';
|
|
7
|
+
var script = {
|
|
8
|
+
name: 'GlGridLayout',
|
|
9
|
+
props: {
|
|
10
|
+
value: {
|
|
11
|
+
type: Object,
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
isStatic: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
required: false,
|
|
17
|
+
default: true
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
data() {
|
|
21
|
+
return {
|
|
22
|
+
grid: undefined,
|
|
23
|
+
gridPanels: []
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
computed: {
|
|
27
|
+
gridConfig() {
|
|
28
|
+
return this.value.panels.map(panel => {
|
|
29
|
+
const {
|
|
30
|
+
gridAttributes,
|
|
31
|
+
...otherProps
|
|
32
|
+
} = panel;
|
|
33
|
+
return {
|
|
34
|
+
...this.getPanelGridItemConfig(panel),
|
|
35
|
+
props: otherProps
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
watch: {
|
|
41
|
+
isStatic(value) {
|
|
42
|
+
var _this$grid;
|
|
43
|
+
(_this$grid = this.grid) === null || _this$grid === void 0 ? void 0 : _this$grid.setStatic(value);
|
|
44
|
+
},
|
|
45
|
+
gridConfig: {
|
|
46
|
+
handler(config) {
|
|
47
|
+
var _this$grid2;
|
|
48
|
+
(_this$grid2 = this.grid) === null || _this$grid2 === void 0 ? void 0 : _this$grid2.load(config);
|
|
49
|
+
},
|
|
50
|
+
deep: true
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Data flow:
|
|
54
|
+
* 1. Initial: mounted → initGridStack() → grid.load(gridConfig) →
|
|
55
|
+
* grid.getGridItems() → initGridPanelSlots → gridPanels populated with DOM references
|
|
56
|
+
* 2. Updates: value.panels changes → two parallel paths:
|
|
57
|
+
* a. gridConfig changes → grid.load() updates grid layout (but not gridPanels)
|
|
58
|
+
* b. this watcher updates gridPanels with new panel properties
|
|
59
|
+
*/
|
|
60
|
+
'value.panels': {
|
|
61
|
+
handler(newPanels) {
|
|
62
|
+
if (this.gridPanels.length === 0) return;
|
|
63
|
+
|
|
64
|
+
// Only update panels that have changed to improve performance
|
|
65
|
+
newPanels.forEach(updatedPanel => {
|
|
66
|
+
const panel = this.gridPanels.find(p => p.id === updatedPanel.id);
|
|
67
|
+
if (panel) {
|
|
68
|
+
// Exclude `gridAttributes` from being included in the panel props as it's not a valid prop for the panel component
|
|
69
|
+
const panelPropsWithoutGridAttributes = pickBy(updatedPanel, (_, k) => k !== 'gridAttributes');
|
|
70
|
+
panel.props = {
|
|
71
|
+
...panelPropsWithoutGridAttributes
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
deep: true
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
mounted() {
|
|
80
|
+
this.initGridStack();
|
|
81
|
+
},
|
|
82
|
+
beforeDestroy() {
|
|
83
|
+
var _this$grid3;
|
|
84
|
+
const removeDom = Boolean(this.$el.parentElement);
|
|
85
|
+
(_this$grid3 = this.grid) === null || _this$grid3 === void 0 ? void 0 : _this$grid3.destroy(removeDom);
|
|
86
|
+
},
|
|
87
|
+
methods: {
|
|
88
|
+
// TODO: Refactor this to use render methods once Vue 3 migration is complete
|
|
89
|
+
// https://gitlab.com/gitlab-org/gitlab/-/issues/549095
|
|
90
|
+
async mountGridComponents(panels) {
|
|
91
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
92
|
+
scrollIntoView: false
|
|
93
|
+
};
|
|
94
|
+
// Ensure new panels are always rendered first
|
|
95
|
+
await this.$nextTick();
|
|
96
|
+
panels.forEach(panel => {
|
|
97
|
+
var _this$$refs$panelWrap;
|
|
98
|
+
const wrapper = (_this$$refs$panelWrap = this.$refs.panelWrappers) === null || _this$$refs$panelWrap === void 0 ? void 0 : _this$$refs$panelWrap.find(w => w.id === panel.id);
|
|
99
|
+
const widgetContentEl = panel.el.querySelector('.grid-stack-item-content');
|
|
100
|
+
if (wrapper && widgetContentEl) {
|
|
101
|
+
widgetContentEl.appendChild(wrapper);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
if (options.scrollIntoView) {
|
|
105
|
+
const mostRecent = panels[panels.length - 1];
|
|
106
|
+
mostRecent.el.scrollIntoView({
|
|
107
|
+
behavior: 'smooth'
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
getGridItemForElement(el) {
|
|
112
|
+
return this.gridConfig.find(item => item.id === el.getAttribute('gs-id'));
|
|
113
|
+
},
|
|
114
|
+
initGridPanelSlots(gridElements) {
|
|
115
|
+
if (!gridElements) return;
|
|
116
|
+
this.gridPanels = gridElements.map(el => ({
|
|
117
|
+
...this.getGridItemForElement(el),
|
|
118
|
+
el
|
|
119
|
+
}));
|
|
120
|
+
this.mountGridComponents(this.gridPanels);
|
|
121
|
+
},
|
|
122
|
+
initGridStack() {
|
|
123
|
+
// See https://github.com/gridstack/gridstack.js/tree/master/doc#grid-options
|
|
124
|
+
this.grid = GridStack.init({
|
|
125
|
+
// Uniform gap between panels
|
|
126
|
+
margin: '8px',
|
|
127
|
+
// CSS Selector for finding the drag handle element
|
|
128
|
+
handle: '.grid-stack-item-handle',
|
|
129
|
+
/* Magic number 125px:
|
|
130
|
+
* After allowing for padding, and the panel title row, this leaves us with minimum 48px height for the cell content.
|
|
131
|
+
* This means text/content with our spacing scale can fit up to 49px without scrolling.
|
|
132
|
+
*/
|
|
133
|
+
cellHeight: '125px',
|
|
134
|
+
// Setting 1 in minRow prevents the grid collapsing when all panels are removed
|
|
135
|
+
minRow: 1,
|
|
136
|
+
// Define the number of columns for anything below a set width, defaults to fill the available space
|
|
137
|
+
columnOpts: {
|
|
138
|
+
breakpoints: [{
|
|
139
|
+
w: breakpoints.md,
|
|
140
|
+
c: 1
|
|
141
|
+
}]
|
|
142
|
+
},
|
|
143
|
+
alwaysShowResizeHandle: true,
|
|
144
|
+
animate: true,
|
|
145
|
+
float: true,
|
|
146
|
+
// Toggles user-customization of grid layout
|
|
147
|
+
staticGrid: this.isStatic
|
|
148
|
+
}, this.$refs.grid).load(this.gridConfig);
|
|
149
|
+
|
|
150
|
+
// Sync Vue components array with gridstack items
|
|
151
|
+
this.initGridPanelSlots(this.grid.getGridItems());
|
|
152
|
+
this.grid.on('dragstart', () => {
|
|
153
|
+
this.$el.classList.add(CURSOR_GRABBING_CLASS);
|
|
154
|
+
});
|
|
155
|
+
this.grid.on('dragstop', () => {
|
|
156
|
+
this.$el.classList.remove(CURSOR_GRABBING_CLASS);
|
|
157
|
+
});
|
|
158
|
+
this.grid.on('change', (_, items) => {
|
|
159
|
+
if (!items) return;
|
|
160
|
+
this.emitLayoutChanges(items);
|
|
161
|
+
});
|
|
162
|
+
this.grid.on('added', (_, items) => {
|
|
163
|
+
this.addGridPanels(items);
|
|
164
|
+
});
|
|
165
|
+
this.grid.on('removed', (_, items) => {
|
|
166
|
+
this.removeGridPanels(items);
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
getPanelGridItemConfig(_ref) {
|
|
170
|
+
let {
|
|
171
|
+
gridAttributes: {
|
|
172
|
+
xPos,
|
|
173
|
+
yPos,
|
|
174
|
+
width,
|
|
175
|
+
height,
|
|
176
|
+
minHeight,
|
|
177
|
+
minWidth,
|
|
178
|
+
maxHeight,
|
|
179
|
+
maxWidth
|
|
180
|
+
},
|
|
181
|
+
id
|
|
182
|
+
} = _ref;
|
|
183
|
+
const filterUndefinedValues = obj => pickBy(obj, value => value !== undefined);
|
|
184
|
+
|
|
185
|
+
// GridStack renders undefined layout values so we need to filter them out.
|
|
186
|
+
return filterUndefinedValues({
|
|
187
|
+
x: xPos,
|
|
188
|
+
y: yPos,
|
|
189
|
+
w: width,
|
|
190
|
+
h: height,
|
|
191
|
+
minH: minHeight,
|
|
192
|
+
minW: minWidth,
|
|
193
|
+
maxH: maxHeight,
|
|
194
|
+
maxW: maxWidth,
|
|
195
|
+
id
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
convertToGridAttributes(gridStackItem) {
|
|
199
|
+
return {
|
|
200
|
+
yPos: gridStackItem.y,
|
|
201
|
+
xPos: gridStackItem.x,
|
|
202
|
+
width: gridStackItem.w,
|
|
203
|
+
height: gridStackItem.h
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
removeGridPanels(items) {
|
|
207
|
+
items.forEach(item => {
|
|
208
|
+
const index = this.gridPanels.findIndex(c => c.id === item.id);
|
|
209
|
+
this.gridPanels.splice(index, 1);
|
|
210
|
+
// Finally, remove the gridstack element
|
|
211
|
+
item.el.remove();
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
addGridPanels(items) {
|
|
215
|
+
const newPanels = items.map(_ref2 => {
|
|
216
|
+
let {
|
|
217
|
+
grid,
|
|
218
|
+
...rest
|
|
219
|
+
} = _ref2;
|
|
220
|
+
return {
|
|
221
|
+
...rest
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
this.gridPanels.push(...newPanels);
|
|
225
|
+
this.mountGridComponents(newPanels, {
|
|
226
|
+
scrollIntoView: true
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
emitLayoutChanges(items) {
|
|
230
|
+
/**
|
|
231
|
+
* Uses JSON parse and stringify to remove object references.
|
|
232
|
+
* Lodash's `cloneDeep` retains circular references.
|
|
233
|
+
* See https://github.com/lodash/lodash/issues/4710#issuecomment-606892867 for details on cloneDeep circular references
|
|
234
|
+
* See https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm for the underlying mechanism used by Lodash
|
|
235
|
+
*/
|
|
236
|
+
const newValue = JSON.parse(JSON.stringify(this.value));
|
|
237
|
+
items.forEach(item => {
|
|
238
|
+
const panel = newValue.panels.find(p => p.id === item.id);
|
|
239
|
+
if (!panel) return;
|
|
240
|
+
panel.gridAttributes = {
|
|
241
|
+
...panel.gridAttributes,
|
|
242
|
+
...this.convertToGridAttributes(item)
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
this.$emit('input', newValue);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
/* script */
|
|
251
|
+
const __vue_script__ = script;
|
|
252
|
+
|
|
253
|
+
/* template */
|
|
254
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"grid",staticClass:"grid-stack",attrs:{"data-testid":"gridstack-grid"}},_vm._l((_vm.gridPanels),function(panel){return _c('div',{key:panel.id,ref:"panelWrappers",refInFor:true,staticClass:"gl-h-full",class:{ 'gl-cursor-grab': !_vm.isStatic },attrs:{"id":panel.id,"data-testid":"gridstack-panel"}},[_vm._t("panel",null,null,{ panel: panel.props })],2)}),0)};
|
|
255
|
+
var __vue_staticRenderFns__ = [];
|
|
256
|
+
|
|
257
|
+
/* style */
|
|
258
|
+
const __vue_inject_styles__ = undefined;
|
|
259
|
+
/* scoped */
|
|
260
|
+
const __vue_scope_id__ = undefined;
|
|
261
|
+
/* module identifier */
|
|
262
|
+
const __vue_module_identifier__ = undefined;
|
|
263
|
+
/* functional template */
|
|
264
|
+
const __vue_is_functional_template__ = false;
|
|
265
|
+
/* style inject */
|
|
266
|
+
|
|
267
|
+
/* style inject SSR */
|
|
268
|
+
|
|
269
|
+
/* style inject shadow dom */
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
const __vue_component__ = /*#__PURE__*/__vue_normalize__(
|
|
274
|
+
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
|
|
275
|
+
__vue_inject_styles__,
|
|
276
|
+
__vue_script__,
|
|
277
|
+
__vue_scope_id__,
|
|
278
|
+
__vue_is_functional_template__,
|
|
279
|
+
__vue_module_identifier__,
|
|
280
|
+
false,
|
|
281
|
+
undefined,
|
|
282
|
+
undefined,
|
|
283
|
+
undefined
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
export { __vue_component__ as default };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import uniqueId from 'lodash/uniqueId';
|
|
2
|
+
|
|
3
|
+
const getUniquePanelId = () => uniqueId('panel-');
|
|
4
|
+
const dashboard = {
|
|
5
|
+
id: 'analytics_overview',
|
|
6
|
+
slug: 'analytics_overview',
|
|
7
|
+
title: 'Analytics Overview',
|
|
8
|
+
description: 'This is a dashboard',
|
|
9
|
+
userDefined: true,
|
|
10
|
+
panels: [{
|
|
11
|
+
title: 'Test A',
|
|
12
|
+
gridAttributes: {
|
|
13
|
+
width: 3,
|
|
14
|
+
height: 3,
|
|
15
|
+
xPos: 0,
|
|
16
|
+
yPos: 0
|
|
17
|
+
},
|
|
18
|
+
id: getUniquePanelId()
|
|
19
|
+
}, {
|
|
20
|
+
title: 'Test B',
|
|
21
|
+
gridAttributes: {
|
|
22
|
+
width: 2,
|
|
23
|
+
height: 4,
|
|
24
|
+
xPos: 1,
|
|
25
|
+
yPos: 1,
|
|
26
|
+
minHeight: 2,
|
|
27
|
+
minWidth: 2
|
|
28
|
+
},
|
|
29
|
+
id: getUniquePanelId()
|
|
30
|
+
}],
|
|
31
|
+
status: null,
|
|
32
|
+
errors: null
|
|
33
|
+
};
|
|
34
|
+
const mockPanel = {
|
|
35
|
+
title: 'Test A',
|
|
36
|
+
gridAttributes: {
|
|
37
|
+
width: 1,
|
|
38
|
+
height: 2,
|
|
39
|
+
xPos: 0,
|
|
40
|
+
yPos: 3,
|
|
41
|
+
minWidth: 1,
|
|
42
|
+
minHeight: 2,
|
|
43
|
+
maxWidth: 1,
|
|
44
|
+
maxHeight: 2
|
|
45
|
+
},
|
|
46
|
+
id: getUniquePanelId()
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { dashboard, getUniquePanelId, mockPanel };
|