adore-gantt 2.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/src/popup.js ADDED
@@ -0,0 +1,61 @@
1
+ export default class Popup {
2
+ constructor(parent, popup_func, gantt) {
3
+ this.parent = parent;
4
+ this.popup_func = popup_func;
5
+ this.gantt = gantt;
6
+
7
+ this.make();
8
+ }
9
+
10
+ make() {
11
+ this.parent.innerHTML = `
12
+ <div class="title"></div>
13
+ <div class="subtitle"></div>
14
+ <div class="details"></div>
15
+ <div class="actions"></div>
16
+ `;
17
+ this.hide();
18
+
19
+ this.title = this.parent.querySelector('.title');
20
+ this.subtitle = this.parent.querySelector('.subtitle');
21
+ this.details = this.parent.querySelector('.details');
22
+ this.actions = this.parent.querySelector('.actions');
23
+ }
24
+
25
+ show({ x, y, task, target }) {
26
+ this.actions.innerHTML = '';
27
+ let html = this.popup_func({
28
+ task,
29
+ chart: this.gantt,
30
+ get_title: () => this.title,
31
+ set_title: (title) => (this.title.innerHTML = title),
32
+ get_subtitle: () => this.subtitle,
33
+ set_subtitle: (subtitle) => (this.subtitle.innerHTML = subtitle),
34
+ get_details: () => this.details,
35
+ set_details: (details) => (this.details.innerHTML = details),
36
+ add_action: (html, func) => {
37
+ let action = this.gantt.create_el({
38
+ classes: 'action-btn',
39
+ type: 'button',
40
+ append_to: this.actions,
41
+ });
42
+ if (typeof html === 'function') html = html(task);
43
+ action.innerHTML = html;
44
+ action.onclick = (e) => func(task, this.gantt, e);
45
+ },
46
+ });
47
+ if (html === false) return;
48
+ if (html) this.parent.innerHTML = html;
49
+
50
+ if (this.actions.innerHTML === '') this.actions.remove();
51
+ else this.parent.appendChild(this.actions);
52
+
53
+ this.parent.style.left = x + 10 + 'px';
54
+ this.parent.style.top = y - 10 + 'px';
55
+ this.parent.classList.remove('hide');
56
+ }
57
+
58
+ hide() {
59
+ this.parent.classList.add('hide');
60
+ }
61
+ }
@@ -0,0 +1,87 @@
1
+ :root {
2
+ --g-bar-stroke-dark: #c6ccd2;
3
+ --g-border-color-dark: #616161;
4
+ --g-bar-color-dark: #616161;
5
+ --g-bg-dark: #3e3e3e;
6
+ --g-light-border-color-dark: #3e3e3e;
7
+ --g-text-muted-dark: #eee;
8
+ --g-text-light-dark: #ececec;
9
+ --g-text-color-dark: #f7f7f7;
10
+ --g-progress-color: #8a8aff;
11
+ }
12
+
13
+ .dark > .gantt-container .gantt {
14
+ & .grid-row {
15
+ fill: #252525;
16
+ }
17
+
18
+ & .row-line {
19
+ stroke: var(--g-light-border-color-dark);
20
+ }
21
+
22
+ & .tick {
23
+ stroke: var(--g-border-color-dark);
24
+ }
25
+
26
+ & .arrow {
27
+ stroke: var(--g-text-muted-dark);
28
+ }
29
+
30
+ & .bar {
31
+ fill: var(--g-bar-color-dark);
32
+ stroke: none;
33
+ }
34
+
35
+ & .bar-progress {
36
+ fill: var(--g-progress-color);
37
+ }
38
+
39
+ & .bar-invalid {
40
+ fill: transparent;
41
+ stroke: var(--g-bar-stroke-dark);
42
+
43
+ & ~ .bar-label {
44
+ fill: var(--g-text-light-dark);
45
+ }
46
+ }
47
+
48
+ & .bar-label.big {
49
+ fill: var(--g-text-light-dark);
50
+ }
51
+
52
+ & .bar-wrapper {
53
+ &:hover {
54
+ .bar {
55
+ fill: lighten(var(--g-bar-color-dark, 5));
56
+ }
57
+
58
+ & .bar-progress {
59
+ fill: lighten(var(--g-progress-color, 5));
60
+ }
61
+ }
62
+
63
+ &.active {
64
+ .bar {
65
+ fill: lighten(var(--g-bar-color-dark, 5));
66
+ }
67
+
68
+ & .bar-progress {
69
+ fill: lighten(var(--g-progress-color, 5));
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ .dark > .gantt-container {
76
+ & .grid-header {
77
+ background-color: #252525;
78
+ }
79
+
80
+ & .popup-wrapper {
81
+ background-color: #333;
82
+
83
+ & .title {
84
+ border-color: lighten(var(--g-progress-color, 5));
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,343 @@
1
+ @import './light.css';
2
+
3
+ .gantt-container {
4
+ line-height: 14.5px;
5
+ position: relative;
6
+ overflow: auto;
7
+ font-size: 12px;
8
+ height: var(--gv-grid-height);
9
+ width: 100%;
10
+ border-radius: 8px;
11
+
12
+ & .popup-wrapper {
13
+ position: absolute;
14
+ top: 0;
15
+ left: 0;
16
+ background: #fff;
17
+ box-shadow: 0px 10px 24px -3px rgba(0, 0, 0, 0.2);
18
+ padding: 10px;
19
+ border-radius: 5px;
20
+ width: max-content;
21
+ z-index: 1000;
22
+
23
+ & .title {
24
+ margin-bottom: 2px;
25
+ color: var(--g-text-dark);
26
+ font-size: 0.85rem;
27
+ font-weight: 650;
28
+ line-height: 15px;
29
+ }
30
+
31
+ & .subtitle {
32
+ color: var(--g-text-dark);
33
+ font-size: 0.8rem;
34
+ margin-bottom: 5px;
35
+ }
36
+
37
+ & .details {
38
+ color: var(--g-text-muted);
39
+ font-size: 0.7rem;
40
+ }
41
+
42
+ & .actions {
43
+ margin-top: 10px;
44
+ margin-left: 3px;
45
+ }
46
+
47
+ & .action-btn {
48
+ border: none;
49
+ padding: 5px 8px;
50
+ background-color: var(--g-popup-actions);
51
+ border-right: 1px solid var(--g-text-light);
52
+
53
+ &:hover {
54
+ background-color: brightness(97%);
55
+ }
56
+
57
+ &:first-child {
58
+ border-top-left-radius: 4px;
59
+ border-bottom-left-radius: 4px;
60
+ }
61
+
62
+ &:last-child {
63
+ border-right: none;
64
+ border-top-right-radius: 4px;
65
+ border-bottom-right-radius: 4px;
66
+ }
67
+ }
68
+ }
69
+
70
+ & .grid-header {
71
+ height: calc(
72
+ var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px
73
+ );
74
+ background-color: var(--g-header-background);
75
+ position: sticky;
76
+ top: 0;
77
+ left: 0;
78
+ border-bottom: 1px solid var(--g-row-border-color);
79
+ z-index: 1000;
80
+ }
81
+
82
+ & .lower-text,
83
+ & .upper-text {
84
+ text-anchor: middle;
85
+ }
86
+
87
+ & .upper-header {
88
+ height: var(--gv-upper-header-height);
89
+ }
90
+
91
+ & .lower-header {
92
+ height: var(--gv-lower-header-height);
93
+ }
94
+
95
+ & .lower-text {
96
+ font-size: 12px;
97
+ position: absolute;
98
+ width: calc(var(--gv-column-width) * 0.8);
99
+ height: calc(var(--gv-lower-header-height) * 0.8);
100
+ margin: 0 calc(var(--gv-column-width) * 0.1);
101
+ align-content: center;
102
+ text-align: center;
103
+ color: var(--g-text-muted);
104
+ }
105
+
106
+ & .upper-text {
107
+ position: absolute;
108
+ width: fit-content;
109
+ font-weight: 500;
110
+ font-size: 14px;
111
+ color: var(--g-text-dark);
112
+ height: calc(var(--gv-lower-header-height) * 0.66);
113
+ }
114
+
115
+ & .current-upper {
116
+ position: sticky;
117
+ left: 0 !important;
118
+ padding-left: 17px;
119
+ background: white;
120
+ }
121
+
122
+ & .side-header {
123
+ position: sticky;
124
+ top: 0;
125
+ right: 0;
126
+ float: right;
127
+
128
+ z-index: 1000;
129
+ line-height: 20px;
130
+ font-weight: 400;
131
+ width: max-content;
132
+ margin-left: auto;
133
+ padding-right: 10px;
134
+ padding-top: 10px;
135
+ background: var(--g-header-background);
136
+ display: flex;
137
+ }
138
+
139
+ & .side-header * {
140
+ transition-property: background-color;
141
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
142
+ transition-duration: 150ms;
143
+ background-color: var(--g-actions-background);
144
+ border-radius: 0.5rem;
145
+ border: none;
146
+ padding: 5px 8px;
147
+ color: var(--g-text-dark);
148
+ font-size: 14px;
149
+ letter-spacing: 0.02em;
150
+ font-weight: 420;
151
+ box-sizing: content-box;
152
+
153
+ margin-right: 5px;
154
+
155
+ &:last-child {
156
+ margin-right: 0;
157
+ }
158
+
159
+ &:hover {
160
+ filter: brightness(97.5%);
161
+ }
162
+ }
163
+
164
+ & .side-header select {
165
+ width: 60px;
166
+ padding-top: 2px;
167
+ padding-bottom: 2px;
168
+ }
169
+ & .side-header select:focus {
170
+ outline: none;
171
+ }
172
+
173
+ & .date-range-highlight {
174
+ background-color: var(--g-progress-color);
175
+ border-radius: 12px;
176
+ height: calc(var(--gv-lower-header-height) - 6px);
177
+ top: calc(var(--gv-upper-header-height) + 5px);
178
+ position: absolute;
179
+ }
180
+
181
+ & .current-highlight {
182
+ position: absolute;
183
+ background: var(--g-today-highlight);
184
+ width: 1px;
185
+ z-index: 999;
186
+ }
187
+
188
+ & .current-ball-highlight {
189
+ position: absolute;
190
+ background: var(--g-today-highlight);
191
+ z-index: 1001;
192
+ border-radius: 50%;
193
+ }
194
+
195
+ & .current-date-highlight {
196
+ background: var(--g-today-highlight);
197
+ color: var(--g-text-light);
198
+ border-radius: 5px;
199
+ }
200
+
201
+ & .holiday-label {
202
+ position: absolute;
203
+ top: 0;
204
+ left: 0;
205
+ opacity: 0;
206
+ z-index: 1000;
207
+ background: --g-weekend-label-color;
208
+ border-radius: 5px;
209
+ padding: 2px 5px;
210
+
211
+ &.show {
212
+ opacity: 100;
213
+ }
214
+ }
215
+
216
+ & .extras {
217
+ position: sticky;
218
+ left: 0px;
219
+
220
+ & .adjust {
221
+ position: absolute;
222
+ left: 8px;
223
+ top: calc(var(--gv-grid-height) - 60px);
224
+ background-color: rgba(0, 0, 0, 0.7);
225
+ color: white;
226
+ border: none;
227
+ padding: 8px;
228
+ border-radius: 3px;
229
+ }
230
+ }
231
+
232
+ .hide {
233
+ display: none;
234
+ }
235
+ }
236
+
237
+ .gantt {
238
+ user-select: none;
239
+ -webkit-user-select: none;
240
+ position: absolute;
241
+
242
+ & .grid-background {
243
+ fill: none;
244
+ }
245
+
246
+ & .grid-row {
247
+ fill: var(--g-row-color);
248
+ }
249
+
250
+ & .row-line {
251
+ stroke: var(--g-border-color);
252
+ }
253
+
254
+ & .tick {
255
+ stroke: var(--g-tick-color);
256
+ stroke-width: 0.4;
257
+
258
+ &.thick {
259
+ stroke: var(--g-tick-color-thick);
260
+ stroke-width: 0.7;
261
+ }
262
+ }
263
+
264
+ & .arrow {
265
+ fill: none;
266
+ stroke: var(--g-arrow-color);
267
+ stroke-width: 1.5;
268
+ }
269
+
270
+ & .bar-wrapper .bar {
271
+ fill: var(--g-bar-color);
272
+ stroke: var(--g-bar-border);
273
+ stroke-width: 0;
274
+ transition: stroke-width 0.3s ease;
275
+ }
276
+
277
+ & .bar-progress {
278
+ fill: var(--g-progress-color);
279
+ border-radius: 4px;
280
+ }
281
+
282
+ & .bar-expected-progress {
283
+ fill: var(--g-expected-progress);
284
+ }
285
+
286
+ & .bar-invalid {
287
+ fill: transparent;
288
+ stroke: var(--g-bar-border);
289
+ stroke-width: 1;
290
+ stroke-dasharray: 5;
291
+
292
+ & ~ .bar-label {
293
+ fill: var(--g-text-light);
294
+ }
295
+ }
296
+
297
+ & .bar-label {
298
+ fill: var(--g-text-dark);
299
+ dominant-baseline: central;
300
+ font-family: Helvetica;
301
+ font-size: 13px;
302
+ font-weight: 400;
303
+
304
+ &.big {
305
+ fill: var(--g-text-dark);
306
+ text-anchor: start;
307
+ }
308
+ }
309
+
310
+ & .handle {
311
+ fill: var(--g-handle-color);
312
+ opacity: 0;
313
+ transition: opacity 0.3s ease;
314
+ &.active,
315
+ &.visible {
316
+ cursor: ew-resize;
317
+ opacity: 1;
318
+ }
319
+ }
320
+
321
+ & .handle.progress {
322
+ fill: var(--g-text-muted);
323
+ }
324
+
325
+ & .bar-wrapper {
326
+ cursor: pointer;
327
+
328
+ & .bar {
329
+ outline: 1px solid var(--g-row-border-color);
330
+ border-radius: 3px;
331
+ }
332
+
333
+ &:hover {
334
+ .bar {
335
+ transition: transform 0.3s ease;
336
+ }
337
+
338
+ .date-range-highlight {
339
+ display: block;
340
+ }
341
+ }
342
+ }
343
+ }
@@ -0,0 +1,22 @@
1
+ :root {
2
+ --g-arrow-color: #1f2937;
3
+ --g-bar-color: #fff;
4
+ --g-bar-border: #fff;
5
+ --g-tick-color-thick: #ededed;
6
+ --g-tick-color: #f3f3f3;
7
+ --g-actions-background: #f3f3f3;
8
+ --g-border-color: #ebeff2;
9
+ --g-text-muted: #7c7c7c;
10
+ --g-text-light: #fff;
11
+ --g-text-dark: #171717;
12
+ --g-progress-color: #dbdbdb;
13
+ --g-handle-color: #37352f;
14
+ --g-weekend-label-color: #dcdce4;
15
+ --g-expected-progress: #c4c4e9;
16
+ --g-header-background: #fff;
17
+ --g-row-color: #fdfdfd;
18
+ --g-row-border-color: #c7c7c7;
19
+ --g-today-highlight: #37352f;
20
+ --g-popup-actions: #ebeff2;
21
+ --g-weekend-highlight-color: #f7f7f7;
22
+ }
@@ -0,0 +1,135 @@
1
+ export function $(expr, con) {
2
+ return typeof expr === 'string'
3
+ ? (con || document).querySelector(expr)
4
+ : expr || null;
5
+ }
6
+
7
+ export function createSVG(tag, attrs) {
8
+ const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);
9
+ for (let attr in attrs) {
10
+ if (attr === 'append_to') {
11
+ const parent = attrs.append_to;
12
+ parent.appendChild(elem);
13
+ } else if (attr === 'innerHTML') {
14
+ elem.innerHTML = attrs.innerHTML;
15
+ } else if (attr === 'clipPath') {
16
+ elem.setAttribute('clip-path', 'url(#' + attrs[attr] + ')');
17
+ } else {
18
+ elem.setAttribute(attr, attrs[attr]);
19
+ }
20
+ }
21
+ return elem;
22
+ }
23
+
24
+ export function animateSVG(svgElement, attr, from, to) {
25
+ const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);
26
+
27
+ if (animatedSvgElement === svgElement) {
28
+ // triggered 2nd time programmatically
29
+ // trigger artificial click event
30
+ const event = document.createEvent('HTMLEvents');
31
+ event.initEvent('click', true, true);
32
+ event.eventName = 'click';
33
+ animatedSvgElement.dispatchEvent(event);
34
+ }
35
+ }
36
+
37
+ function getAnimationElement(
38
+ svgElement,
39
+ attr,
40
+ from,
41
+ to,
42
+ dur = '0.4s',
43
+ begin = '0.1s',
44
+ ) {
45
+ const animEl = svgElement.querySelector('animate');
46
+ if (animEl) {
47
+ $.attr(animEl, {
48
+ attributeName: attr,
49
+ from,
50
+ to,
51
+ dur,
52
+ begin: 'click + ' + begin, // artificial click
53
+ });
54
+ return svgElement;
55
+ }
56
+
57
+ const animateElement = createSVG('animate', {
58
+ attributeName: attr,
59
+ from,
60
+ to,
61
+ dur,
62
+ begin,
63
+ calcMode: 'spline',
64
+ values: from + ';' + to,
65
+ keyTimes: '0; 1',
66
+ keySplines: cubic_bezier('ease-out'),
67
+ });
68
+ svgElement.appendChild(animateElement);
69
+
70
+ return svgElement;
71
+ }
72
+
73
+ function cubic_bezier(name) {
74
+ return {
75
+ ease: '.25 .1 .25 1',
76
+ linear: '0 0 1 1',
77
+ 'ease-in': '.42 0 1 1',
78
+ 'ease-out': '0 0 .58 1',
79
+ 'ease-in-out': '.42 0 .58 1',
80
+ }[name];
81
+ }
82
+
83
+ $.on = (element, event, selector, callback) => {
84
+ if (!callback) {
85
+ callback = selector;
86
+ $.bind(element, event, callback);
87
+ } else {
88
+ $.delegate(element, event, selector, callback);
89
+ }
90
+ };
91
+
92
+ $.off = (element, event, handler) => {
93
+ element.removeEventListener(event, handler);
94
+ };
95
+
96
+ $.bind = (element, event, callback) => {
97
+ event.split(/\s+/).forEach(function (event) {
98
+ element.addEventListener(event, callback);
99
+ });
100
+ };
101
+
102
+ $.delegate = (element, event, selector, callback) => {
103
+ element.addEventListener(event, function (e) {
104
+ const delegatedTarget = e.target.closest(selector);
105
+ if (delegatedTarget) {
106
+ e.delegatedTarget = delegatedTarget;
107
+ callback.call(this, e, delegatedTarget);
108
+ }
109
+ });
110
+ };
111
+
112
+ $.closest = (selector, element) => {
113
+ if (!element) return null;
114
+
115
+ if (element.matches(selector)) {
116
+ return element;
117
+ }
118
+
119
+ return $.closest(selector, element.parentNode);
120
+ };
121
+
122
+ $.attr = (element, attr, value) => {
123
+ if (!value && typeof attr === 'string') {
124
+ return element.getAttribute(attr);
125
+ }
126
+
127
+ if (typeof attr === 'object') {
128
+ for (let key in attr) {
129
+ $.attr(element, key, attr[key]);
130
+ }
131
+ return;
132
+ }
133
+
134
+ element.setAttribute(attr, value);
135
+ };