@operato/gantt 2.0.0-beta.14 → 2.0.0-beta.17
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 +28 -0
- package/dist/src/gantt-chart-controller.d.ts +32 -0
- package/dist/src/gantt-chart-controller.js +393 -0
- package/dist/src/gantt-chart-controller.js.map +1 -0
- package/dist/src/locales.d.ts +52 -0
- package/dist/src/locales.js +79 -0
- package/dist/src/locales.js.map +1 -0
- package/dist/src/ox-gantt-chart.d.ts +10 -17
- package/dist/src/ox-gantt-chart.js +134 -440
- package/dist/src/ox-gantt-chart.js.map +1 -1
- package/dist/src/ox-gantt-resize-splitter.d.ts +2 -3
- package/dist/src/ox-gantt-resize-splitter.js +15 -22
- package/dist/src/ox-gantt-resize-splitter.js.map +1 -1
- package/dist/src/ox-gantt.d.ts +13 -1
- package/dist/src/ox-gantt.js +154 -27
- package/dist/src/ox-gantt.js.map +1 -1
- package/dist/src/ox-task-tooltip.d.ts +12 -0
- package/dist/src/ox-task-tooltip.js +132 -0
- package/dist/src/ox-task-tooltip.js.map +1 -0
- package/dist/src/types.d.ts +10 -3
- package/dist/src/types.js.map +1 -1
- package/dist/stories/ox-gantt.stories.js +91 -85
- package/dist/stories/ox-gantt.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/gantt-chart-controller.ts +470 -0
- package/src/locales.ts +78 -0
- package/src/ox-gantt-chart.ts +141 -487
- package/src/ox-gantt-resize-splitter.ts +18 -25
- package/src/ox-gantt.ts +163 -29
- package/src/ox-task-tooltip.ts +120 -0
- package/src/types.ts +11 -3
- package/stories/ox-gantt.stories.ts +93 -85
- package/translations/en.json +11 -1
- package/translations/ja.json +11 -1
- package/translations/ko.json +11 -1
- package/translations/ms.json +11 -1
- package/translations/zh.json +11 -1
- package/dist/src/locale.d.ts +0 -1
- package/dist/src/locale.js +0 -49
- package/dist/src/locale.js.map +0 -1
- package/src/locale.ts +0 -51
package/dist/src/ox-gantt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { LitElement, html, css } from 'lit';
|
|
3
|
-
import
|
|
3
|
+
import i18next from 'i18next';
|
|
4
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
4
5
|
import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles';
|
|
5
6
|
import { ScrollbarStyles } from '@operato/styles';
|
|
6
7
|
import './ox-gantt-chart.js';
|
|
@@ -12,7 +13,49 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
12
13
|
this.fromDate = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0]; /* beginning of this year */
|
|
13
14
|
this.toDate = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0]; /* end of this year */
|
|
14
15
|
this.extendGridLines = false;
|
|
16
|
+
this.columnConfig = [
|
|
17
|
+
{ name: 'id', label: i18next.t('label.gantt-task-id') || 'ID', visible: true, width: '50px', order: 1 },
|
|
18
|
+
{
|
|
19
|
+
name: 'section',
|
|
20
|
+
label: i18next.t('label.gantt-task-section') || 'section',
|
|
21
|
+
visible: true,
|
|
22
|
+
width: '100px',
|
|
23
|
+
order: 2
|
|
24
|
+
},
|
|
25
|
+
{ name: 'title', label: i18next.t('label.gantt-task-title') || 'title', visible: true, width: '150px', order: 3 },
|
|
26
|
+
{ name: 'type', label: i18next.t('label.gantt-task-type') || 'type', visible: true, width: '100px', order: 4 },
|
|
27
|
+
{
|
|
28
|
+
name: 'startDate',
|
|
29
|
+
label: i18next.t('label.gantt-task-start-date') || 'start date',
|
|
30
|
+
visible: true,
|
|
31
|
+
width: '100px',
|
|
32
|
+
order: 5
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'endDate',
|
|
36
|
+
label: i18next.t('label.gantt-task-end-date') || 'end date',
|
|
37
|
+
visible: true,
|
|
38
|
+
width: '100px',
|
|
39
|
+
order: 6
|
|
40
|
+
},
|
|
41
|
+
{ name: 'tags', label: i18next.t('label.gantt-task-tags') || 'tags', visible: true, width: '100px', order: 7 },
|
|
42
|
+
{
|
|
43
|
+
name: 'progress',
|
|
44
|
+
label: i18next.t('label.gantt-task-progress') || 'progress',
|
|
45
|
+
visible: true,
|
|
46
|
+
width: '100px',
|
|
47
|
+
order: 8
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'dependsOn',
|
|
51
|
+
label: i18next.t('label.gantt-task-previous') || 'previous',
|
|
52
|
+
visible: true,
|
|
53
|
+
width: '100px',
|
|
54
|
+
order: 9
|
|
55
|
+
}
|
|
56
|
+
];
|
|
15
57
|
this._startWidth = 0;
|
|
58
|
+
this._isDragging = false;
|
|
16
59
|
}
|
|
17
60
|
static { this.styles = [
|
|
18
61
|
MDTypeScaleStyles,
|
|
@@ -22,6 +65,7 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
22
65
|
display: block;
|
|
23
66
|
font-family: Arial, sans-serif;
|
|
24
67
|
text-wrap: nowrap;
|
|
68
|
+
position: relative;
|
|
25
69
|
}
|
|
26
70
|
|
|
27
71
|
.container {
|
|
@@ -48,6 +92,7 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
48
92
|
|
|
49
93
|
ox-gantt-resize-splitter {
|
|
50
94
|
width: 4px;
|
|
95
|
+
cursor: ew-resize;
|
|
51
96
|
}
|
|
52
97
|
|
|
53
98
|
table {
|
|
@@ -63,6 +108,7 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
63
108
|
top: -1px;
|
|
64
109
|
z-index: 1;
|
|
65
110
|
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
111
|
+
text-transform: capitalize;
|
|
66
112
|
}
|
|
67
113
|
|
|
68
114
|
th,
|
|
@@ -81,6 +127,10 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
81
127
|
height: 30px;
|
|
82
128
|
box-sizing: border-box;
|
|
83
129
|
}
|
|
130
|
+
|
|
131
|
+
tr.selected {
|
|
132
|
+
background-color: var(--ox-gantt-selected-background-color, var(--md-sys-color-surface-variant));
|
|
133
|
+
}
|
|
84
134
|
`
|
|
85
135
|
]; }
|
|
86
136
|
render() {
|
|
@@ -91,6 +141,7 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
91
141
|
vertical
|
|
92
142
|
@splitter-dragstart=${(e) => this.resizeStart(e)}
|
|
93
143
|
@splitter-drag=${(e) => this.resizeDrag(e)}
|
|
144
|
+
@splitter-dragend=${(e) => this.resizeEnd(e)}
|
|
94
145
|
></ox-gantt-resize-splitter>
|
|
95
146
|
<ox-gantt-chart
|
|
96
147
|
class="chart-container"
|
|
@@ -98,63 +149,133 @@ let OxGantt = class OxGantt extends LitElement {
|
|
|
98
149
|
.fromDate=${this.fromDate}
|
|
99
150
|
.toDate=${this.toDate}
|
|
100
151
|
.tasks=${this.tasks}
|
|
152
|
+
.selectedTaskId=${this.selectedTaskId}
|
|
101
153
|
axis-scale="week-day"
|
|
102
154
|
?extend-grid-lines=${this.extendGridLines}
|
|
155
|
+
@task-clicked=${this.handleTaskClicked}
|
|
103
156
|
></ox-gantt-chart>
|
|
104
157
|
</div>
|
|
105
158
|
`;
|
|
106
159
|
}
|
|
107
160
|
renderTaskTable() {
|
|
161
|
+
const mergedTasks = this.mergeTasksBySection(this.tasks);
|
|
162
|
+
// Sort columns by the configured order
|
|
163
|
+
const sortedColumns = [...this.columnConfig].sort((a, b) => a.order - b.order);
|
|
108
164
|
return html `
|
|
109
165
|
<table>
|
|
110
166
|
<thead>
|
|
111
167
|
<tr>
|
|
112
|
-
|
|
113
|
-
<th>Section</th>
|
|
114
|
-
<th>Title</th>
|
|
115
|
-
<th>Type</th>
|
|
116
|
-
<th>Start Time</th>
|
|
117
|
-
<th>End Time</th>
|
|
118
|
-
<th>Tags</th>
|
|
119
|
-
<th>Progress</th>
|
|
120
|
-
<th>Prev. Task</th>
|
|
168
|
+
${sortedColumns.map(col => (col.visible ? html `<th style="width: ${col.width}">${col.label}</th>` : null))}
|
|
121
169
|
</tr>
|
|
122
170
|
</thead>
|
|
123
171
|
<tbody>
|
|
124
|
-
${
|
|
125
|
-
<tr>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
172
|
+
${mergedTasks.map(({ task, showSection, rowSpan }) => html `
|
|
173
|
+
<tr class="${this.selectedTaskId === task.id ? 'selected' : ''}" @click=${() => this.selectTask(task.id)}>
|
|
174
|
+
${sortedColumns.map(col => {
|
|
175
|
+
if (col.name === 'section') {
|
|
176
|
+
return col.visible && showSection
|
|
177
|
+
? html `<td rowspan="${rowSpan}" style="width: ${col.width}">${task.section?.name || ''}</td>`
|
|
178
|
+
: null;
|
|
179
|
+
}
|
|
180
|
+
return col.visible
|
|
181
|
+
? html `<td style="width: ${col.width}">${this.getTaskFieldValue(task, col.name)}</td>`
|
|
182
|
+
: null;
|
|
183
|
+
})}
|
|
135
184
|
</tr>
|
|
136
185
|
`)}
|
|
137
186
|
</tbody>
|
|
138
187
|
</table>
|
|
139
188
|
`;
|
|
140
189
|
}
|
|
190
|
+
getTaskFieldValue(task, field) {
|
|
191
|
+
switch (field) {
|
|
192
|
+
case 'id':
|
|
193
|
+
return task.id;
|
|
194
|
+
case 'section':
|
|
195
|
+
return task.section?.name || '';
|
|
196
|
+
case 'title':
|
|
197
|
+
return task.title;
|
|
198
|
+
case 'type':
|
|
199
|
+
return task.type;
|
|
200
|
+
case 'startDate':
|
|
201
|
+
return task.startDate.toISOString().split('T')[0];
|
|
202
|
+
case 'endDate':
|
|
203
|
+
return task.endDate.toISOString().split('T')[0];
|
|
204
|
+
case 'tags':
|
|
205
|
+
return task.tags?.join(', ') || '';
|
|
206
|
+
case 'progress':
|
|
207
|
+
return task.progress || '';
|
|
208
|
+
case 'dependsOn':
|
|
209
|
+
return task.dependsOn || '';
|
|
210
|
+
default:
|
|
211
|
+
return '';
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
mergeTasksBySection(tasks) {
|
|
215
|
+
const mergedTasks = [];
|
|
216
|
+
let currentSection = '';
|
|
217
|
+
let rowSpan = 0;
|
|
218
|
+
tasks.forEach((task, index) => {
|
|
219
|
+
if (task.section?.name !== currentSection) {
|
|
220
|
+
currentSection = task.section?.name || '';
|
|
221
|
+
rowSpan = 1;
|
|
222
|
+
mergedTasks.push({ task, showSection: true, rowSpan: 1 });
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
mergedTasks[mergedTasks.length - rowSpan].rowSpan = ++rowSpan;
|
|
226
|
+
mergedTasks.push({ task, showSection: false, rowSpan: 0 });
|
|
227
|
+
}
|
|
228
|
+
if (index === tasks.length - 1 && rowSpan > 0) {
|
|
229
|
+
mergedTasks[mergedTasks.length - rowSpan].rowSpan = rowSpan;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
return mergedTasks;
|
|
233
|
+
}
|
|
234
|
+
selectTask(taskId) {
|
|
235
|
+
this.selectedTaskId = taskId;
|
|
236
|
+
}
|
|
237
|
+
handleTaskClicked(event) {
|
|
238
|
+
this.selectedTaskId = event.detail.taskId;
|
|
239
|
+
}
|
|
141
240
|
firstUpdated(_changedProperties) {
|
|
142
241
|
this.taskContainer.style.width = '254px';
|
|
143
242
|
}
|
|
144
243
|
updated(changes) { }
|
|
145
|
-
syncScroll() {
|
|
146
|
-
|
|
244
|
+
syncScroll(e) {
|
|
245
|
+
const target = e.target;
|
|
246
|
+
if (target === this.taskContainer) {
|
|
247
|
+
// Sync chart scroll with table scroll
|
|
248
|
+
const newScrollTop = this.taskContainer.scrollTop;
|
|
249
|
+
this.ganttChart.setVerticalOffset(newScrollTop);
|
|
250
|
+
// Ensure chart scroll matches table scroll
|
|
251
|
+
if (this.ganttChart.getVerticalOffset() !== newScrollTop) {
|
|
252
|
+
this.ganttChart.setVerticalOffset(newScrollTop);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else if (target === this.ganttChart) {
|
|
256
|
+
// Sync table scroll with chart scroll
|
|
257
|
+
const newScrollTop = this.ganttChart.getVerticalOffset();
|
|
258
|
+
this.taskContainer.scrollTop = newScrollTop;
|
|
259
|
+
// Ensure table scroll matches chart scroll
|
|
260
|
+
this.ganttChart.setVerticalOffset(this.taskContainer.scrollTop);
|
|
261
|
+
}
|
|
147
262
|
}
|
|
148
263
|
resizeStart(e) {
|
|
149
264
|
this._startWidth = e.target?.previousElementSibling?.offsetWidth;
|
|
265
|
+
this._isDragging = true;
|
|
150
266
|
}
|
|
151
267
|
resizeDrag(e) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
268
|
+
if (!this._isDragging)
|
|
269
|
+
return;
|
|
270
|
+
const delta = e.detail;
|
|
271
|
+
const taskContainer = this.taskContainer;
|
|
272
|
+
if (taskContainer) {
|
|
273
|
+
taskContainer.style.width = `${this._startWidth + delta.x}px`;
|
|
156
274
|
}
|
|
157
275
|
}
|
|
276
|
+
resizeEnd(e) {
|
|
277
|
+
this._isDragging = false;
|
|
278
|
+
}
|
|
158
279
|
};
|
|
159
280
|
__decorate([
|
|
160
281
|
property({ type: Array })
|
|
@@ -168,6 +289,12 @@ __decorate([
|
|
|
168
289
|
__decorate([
|
|
169
290
|
property({ type: Boolean, attribute: 'extend-grid-lines' })
|
|
170
291
|
], OxGantt.prototype, "extendGridLines", void 0);
|
|
292
|
+
__decorate([
|
|
293
|
+
state()
|
|
294
|
+
], OxGantt.prototype, "selectedTaskId", void 0);
|
|
295
|
+
__decorate([
|
|
296
|
+
state()
|
|
297
|
+
], OxGantt.prototype, "columnConfig", void 0);
|
|
171
298
|
__decorate([
|
|
172
299
|
query('.container')
|
|
173
300
|
], OxGantt.prototype, "container", void 0);
|
package/dist/src/ox-gantt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-gantt.js","sourceRoot":"","sources":["../../src/ox-gantt.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, PropertyValues, PropertyValueMap } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport './ox-gantt-chart.js'\nimport './ox-gantt-resize-splitter.js'\nimport { OxGanttChart } from './ox-gantt-chart.js'\nimport { Task } from './types.js'\n\n@customElement('ox-gantt')\nexport class OxGantt extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n :host {\n display: block;\n font-family: Arial, sans-serif;\n text-wrap: nowrap;\n }\n\n .container {\n display: flex;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n }\n\n .task-container {\n padding: 0;\n overflow: auto;\n overflow-y: overlay;\n box-sizing: border-box;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n }\n\n .chart-container {\n flex: 1;\n padding: 0;\n box-sizing: border-box;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n }\n\n ox-gantt-resize-splitter {\n width: 4px;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n margin: -1px;\n margin-right: 0;\n }\n\n thead th {\n position: sticky;\n top: -1px;\n z-index: 1;\n background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));\n }\n\n th,\n td {\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n padding: 4px;\n text-align: left;\n }\n\n th {\n height: 40px;\n box-sizing: border-box;\n }\n\n td {\n height: 30px;\n box-sizing: border-box;\n }\n `\n ]\n\n @property({ type: Array }) tasks: Task[] = []\n @property({ type: String, attribute: 'from-date' })\n fromDate: string = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0] /* beginning of this year */\n @property({ type: String, attribute: 'to-date' })\n toDate: string = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0] /* end of this year */\n @property({ type: Boolean, attribute: 'extend-grid-lines' }) extendGridLines: boolean = false\n\n @query('.container') container!: HTMLDivElement\n @query('.task-container') taskContainer!: HTMLDivElement\n @query('.chart-container') chartContainer!: HTMLDivElement\n @query('table') taskTable!: HTMLTableElement\n @query('ox-gantt-chart') ganttChart!: OxGanttChart\n\n private _startWidth: number = 0\n\n render() {\n return html`\n <div class=\"container md-typescale-body-medium\">\n <div class=\"task-container\" @scroll=${this.syncScroll}>${this.renderTaskTable()}</div>\n <ox-gantt-resize-splitter\n vertical\n @splitter-dragstart=${(e: CustomEvent) => this.resizeStart(e)}\n @splitter-drag=${(e: CustomEvent) => this.resizeDrag(e)}\n ></ox-gantt-resize-splitter>\n <ox-gantt-chart\n class=\"chart-container\"\n @scroll=${this.syncScroll}\n .fromDate=${this.fromDate}\n .toDate=${this.toDate}\n .tasks=${this.tasks}\n axis-scale=\"week-day\"\n ?extend-grid-lines=${this.extendGridLines}\n ></ox-gantt-chart>\n </div>\n `\n }\n\n renderTaskTable() {\n return html`\n <table>\n <thead>\n <tr>\n <th>ID</th>\n <th>Section</th>\n <th>Title</th>\n <th>Type</th>\n <th>Start Time</th>\n <th>End Time</th>\n <th>Tags</th>\n <th>Progress</th>\n <th>Prev. Task</th>\n </tr>\n </thead>\n <tbody>\n ${this.tasks.map(\n task => html`\n <tr>\n <td>${task.id}</td>\n <td>${task.section?.name || ''}</td>\n <td>${task.title}</td>\n <td>${task.type}</td>\n <td>${task.startTime.toISOString().split('T')[0]}</td>\n <td>${task.endTime.toISOString().split('T')[0]}</td>\n <td>${task.tags?.join(', ') || ''}</td>\n <td>${task.progress || ''}</td>\n <td>${task.after || ''}</td>\n </tr>\n `\n )}\n </tbody>\n </table>\n `\n }\n\n protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {\n this.taskContainer.style.width = '254px'\n }\n\n updated(changes: PropertyValues<this>) {}\n\n syncScroll() {\n this.ganttChart.setVerticalOffset(this.taskContainer.scrollTop)\n }\n\n resizeStart(e: CustomEvent) {\n this._startWidth = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.offsetWidth\n }\n\n resizeDrag(e: CustomEvent) {\n var delta = e.detail\n var x = (e.target as HTMLElement)?.previousElementSibling as HTMLElement\n if (x) {\n x.style.width = `${this._startWidth + delta.x}px`\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-gantt.js","sourceRoot":"","sources":["../../src/ox-gantt.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, PropertyValues, PropertyValueMap } from 'lit'\nimport i18next from 'i18next'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport './ox-gantt-chart.js'\nimport './ox-gantt-resize-splitter.js'\nimport { OxGanttChart } from './ox-gantt-chart.js'\nimport { ColumnConfig, Task } from './types.js'\n\n@customElement('ox-gantt')\nexport class OxGantt extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n :host {\n display: block;\n font-family: Arial, sans-serif;\n text-wrap: nowrap;\n position: relative;\n }\n\n .container {\n display: flex;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n }\n\n .task-container {\n padding: 0;\n overflow: auto;\n overflow-y: overlay;\n box-sizing: border-box;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n }\n\n .chart-container {\n flex: 1;\n padding: 0;\n box-sizing: border-box;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n }\n\n ox-gantt-resize-splitter {\n width: 4px;\n cursor: ew-resize;\n }\n\n table {\n width: 100%;\n border-collapse: collapse;\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n margin: -1px;\n margin-right: 0;\n }\n\n thead th {\n position: sticky;\n top: -1px;\n z-index: 1;\n background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));\n text-transform: capitalize;\n }\n\n th,\n td {\n border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-on-surface));\n padding: 4px;\n text-align: left;\n }\n\n th {\n height: 40px;\n box-sizing: border-box;\n }\n\n td {\n height: 30px;\n box-sizing: border-box;\n }\n\n tr.selected {\n background-color: var(--ox-gantt-selected-background-color, var(--md-sys-color-surface-variant));\n }\n `\n ]\n\n @property({ type: Array }) tasks: Task[] = []\n @property({ type: String, attribute: 'from-date' })\n fromDate: string = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0] /* beginning of this year */\n @property({ type: String, attribute: 'to-date' })\n toDate: string = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0] /* end of this year */\n @property({ type: Boolean, attribute: 'extend-grid-lines' }) extendGridLines: boolean = false\n\n @state() selectedTaskId?: string\n @state()\n private columnConfig: ColumnConfig[] = [\n { name: 'id', label: i18next.t('label.gantt-task-id') || 'ID', visible: true, width: '50px', order: 1 },\n {\n name: 'section',\n label: i18next.t('label.gantt-task-section') || 'section',\n visible: true,\n width: '100px',\n order: 2\n },\n { name: 'title', label: i18next.t('label.gantt-task-title') || 'title', visible: true, width: '150px', order: 3 },\n { name: 'type', label: i18next.t('label.gantt-task-type') || 'type', visible: true, width: '100px', order: 4 },\n {\n name: 'startDate',\n label: i18next.t('label.gantt-task-start-date') || 'start date',\n visible: true,\n width: '100px',\n order: 5\n },\n {\n name: 'endDate',\n label: i18next.t('label.gantt-task-end-date') || 'end date',\n visible: true,\n width: '100px',\n order: 6\n },\n { name: 'tags', label: i18next.t('label.gantt-task-tags') || 'tags', visible: true, width: '100px', order: 7 },\n {\n name: 'progress',\n label: i18next.t('label.gantt-task-progress') || 'progress',\n visible: true,\n width: '100px',\n order: 8\n },\n {\n name: 'dependsOn',\n label: i18next.t('label.gantt-task-previous') || 'previous',\n visible: true,\n width: '100px',\n order: 9\n }\n ]\n\n @query('.container') container!: HTMLDivElement\n @query('.task-container') taskContainer!: HTMLDivElement\n @query('.chart-container') chartContainer!: HTMLDivElement\n @query('table') taskTable!: HTMLTableElement\n @query('ox-gantt-chart') ganttChart!: OxGanttChart\n\n private _startWidth: number = 0\n private _isDragging: boolean = false\n\n render() {\n return html`\n <div class=\"container md-typescale-body-medium\">\n <div class=\"task-container\" @scroll=${this.syncScroll}>${this.renderTaskTable()}</div>\n <ox-gantt-resize-splitter\n vertical\n @splitter-dragstart=${(e: CustomEvent) => this.resizeStart(e)}\n @splitter-drag=${(e: CustomEvent) => this.resizeDrag(e)}\n @splitter-dragend=${(e: CustomEvent) => this.resizeEnd(e)}\n ></ox-gantt-resize-splitter>\n <ox-gantt-chart\n class=\"chart-container\"\n @scroll=${this.syncScroll}\n .fromDate=${this.fromDate}\n .toDate=${this.toDate}\n .tasks=${this.tasks}\n .selectedTaskId=${this.selectedTaskId}\n axis-scale=\"week-day\"\n ?extend-grid-lines=${this.extendGridLines}\n @task-clicked=${this.handleTaskClicked}\n ></ox-gantt-chart>\n </div>\n `\n }\n\n renderTaskTable() {\n const mergedTasks = this.mergeTasksBySection(this.tasks)\n\n // Sort columns by the configured order\n const sortedColumns = [...this.columnConfig].sort((a, b) => a.order - b.order)\n\n return html`\n <table>\n <thead>\n <tr>\n ${sortedColumns.map(col => (col.visible ? html`<th style=\"width: ${col.width}\">${col.label}</th>` : null))}\n </tr>\n </thead>\n <tbody>\n ${mergedTasks.map(\n ({ task, showSection, rowSpan }) => html`\n <tr class=\"${this.selectedTaskId === task.id ? 'selected' : ''}\" @click=${() => this.selectTask(task.id)}>\n ${sortedColumns.map(col => {\n if (col.name === 'section') {\n return col.visible && showSection\n ? html`<td rowspan=\"${rowSpan}\" style=\"width: ${col.width}\">${task.section?.name || ''}</td>`\n : null\n }\n return col.visible\n ? html`<td style=\"width: ${col.width}\">${this.getTaskFieldValue(task, col.name)}</td>`\n : null\n })}\n </tr>\n `\n )}\n </tbody>\n </table>\n `\n }\n\n getTaskFieldValue(task: Task, field: string) {\n switch (field) {\n case 'id':\n return task.id\n case 'section':\n return task.section?.name || ''\n case 'title':\n return task.title\n case 'type':\n return task.type\n case 'startDate':\n return task.startDate.toISOString().split('T')[0]\n case 'endDate':\n return task.endDate.toISOString().split('T')[0]\n case 'tags':\n return task.tags?.join(', ') || ''\n case 'progress':\n return task.progress || ''\n case 'dependsOn':\n return task.dependsOn || ''\n default:\n return ''\n }\n }\n\n mergeTasksBySection(tasks: Task[]): Array<{ task: Task; showSection: boolean; rowSpan: number }> {\n const mergedTasks = [] as Array<{ task: Task; showSection: boolean; rowSpan: number }>\n let currentSection = ''\n let rowSpan = 0\n\n tasks.forEach((task, index) => {\n if (task.section?.name !== currentSection) {\n currentSection = task.section?.name || ''\n rowSpan = 1\n mergedTasks.push({ task, showSection: true, rowSpan: 1 })\n } else {\n mergedTasks[mergedTasks.length - rowSpan].rowSpan = ++rowSpan\n mergedTasks.push({ task, showSection: false, rowSpan: 0 })\n }\n\n if (index === tasks.length - 1 && rowSpan > 0) {\n mergedTasks[mergedTasks.length - rowSpan].rowSpan = rowSpan\n }\n })\n\n return mergedTasks\n }\n\n selectTask(taskId: string) {\n this.selectedTaskId = taskId\n }\n\n handleTaskClicked(event: CustomEvent) {\n this.selectedTaskId = event.detail.taskId\n }\n\n protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {\n this.taskContainer.style.width = '254px'\n }\n\n updated(changes: PropertyValues<this>) {}\n\n syncScroll(e: Event) {\n const target = e.target as HTMLElement\n if (target === this.taskContainer) {\n // Sync chart scroll with table scroll\n const newScrollTop = this.taskContainer.scrollTop\n this.ganttChart.setVerticalOffset(newScrollTop)\n\n // Ensure chart scroll matches table scroll\n if (this.ganttChart.getVerticalOffset() !== newScrollTop) {\n this.ganttChart.setVerticalOffset(newScrollTop)\n }\n } else if (target === this.ganttChart) {\n // Sync table scroll with chart scroll\n const newScrollTop = this.ganttChart.getVerticalOffset()\n this.taskContainer.scrollTop = newScrollTop\n\n // Ensure table scroll matches chart scroll\n this.ganttChart.setVerticalOffset(this.taskContainer.scrollTop)\n }\n }\n\n resizeStart(e: CustomEvent) {\n this._startWidth = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.offsetWidth\n this._isDragging = true\n }\n\n resizeDrag(e: CustomEvent) {\n if (!this._isDragging) return\n const delta = e.detail\n const taskContainer = this.taskContainer\n\n if (taskContainer) {\n taskContainer.style.width = `${this._startWidth + delta.x}px`\n }\n }\n\n resizeEnd(e: CustomEvent) {\n this._isDragging = false\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
export declare class OxTaskTooltip extends LitElement {
|
|
3
|
+
static styles: import("lit").CSSResult;
|
|
4
|
+
title: string;
|
|
5
|
+
startDate: string;
|
|
6
|
+
endDate: string;
|
|
7
|
+
progress: number;
|
|
8
|
+
type: string;
|
|
9
|
+
show(x: number, y: number): void;
|
|
10
|
+
hide(): void;
|
|
11
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html, css } from 'lit';
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
+
let OxTaskTooltip = class OxTaskTooltip extends LitElement {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.title = '';
|
|
8
|
+
this.startDate = '';
|
|
9
|
+
this.endDate = '';
|
|
10
|
+
this.progress = 0;
|
|
11
|
+
this.type = '';
|
|
12
|
+
}
|
|
13
|
+
static { this.styles = css `
|
|
14
|
+
:host {
|
|
15
|
+
position: fixed; /* position: absolute로 변경 */
|
|
16
|
+
background-color: var(--ox-gantt-tooltip-background-color, var(--md-sys-color-surface, #f9f9f9));
|
|
17
|
+
border: 1px solid var(--ox-gantt-tooltip-border-color, var(--md-sys-color-outline, #ccc));
|
|
18
|
+
padding: var(--spacing-medium, 10px);
|
|
19
|
+
border-radius: var(--spacing-medium, 8px);
|
|
20
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
21
|
+
visibility: hidden;
|
|
22
|
+
z-index: 10;
|
|
23
|
+
max-width: 300px;
|
|
24
|
+
font-family: Roboto;
|
|
25
|
+
font-size: 14px;
|
|
26
|
+
line-height: 1.6;
|
|
27
|
+
color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));
|
|
28
|
+
transition:
|
|
29
|
+
visibility 0.1s,
|
|
30
|
+
opacity 0.1s;
|
|
31
|
+
opacity: 0; /* 초기에는 보이지 않음 */
|
|
32
|
+
}
|
|
33
|
+
:host([visible]) {
|
|
34
|
+
visibility: visible;
|
|
35
|
+
opacity: 1; /* 보일 때는 불투명 */
|
|
36
|
+
}
|
|
37
|
+
.title {
|
|
38
|
+
font-weight: bold;
|
|
39
|
+
font-size: 16px;
|
|
40
|
+
margin-bottom: 8px;
|
|
41
|
+
color: var(--ox-gantt-tooltip-title-color, var(--md-sys-color-primary, #0078d4)); /* 파란색 텍스트 */
|
|
42
|
+
}
|
|
43
|
+
.detail {
|
|
44
|
+
display: grid;
|
|
45
|
+
grid-template-columns: auto auto 1fr;
|
|
46
|
+
gap: 4px;
|
|
47
|
+
align-items: center;
|
|
48
|
+
}
|
|
49
|
+
.label {
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface-variant, #333));
|
|
52
|
+
text-align: right; /* 라벨을 우측 정렬 */
|
|
53
|
+
}
|
|
54
|
+
.colon {
|
|
55
|
+
text-align: center;
|
|
56
|
+
color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));
|
|
57
|
+
}
|
|
58
|
+
.value {
|
|
59
|
+
text-align: left; /* 값을 좌측 정렬 */
|
|
60
|
+
color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));
|
|
61
|
+
}
|
|
62
|
+
`; }
|
|
63
|
+
show(x, y) {
|
|
64
|
+
const tooltipWidth = this.offsetWidth;
|
|
65
|
+
const tooltipHeight = this.offsetHeight;
|
|
66
|
+
const offsetX = 10;
|
|
67
|
+
const offsetY = 10;
|
|
68
|
+
// 기본 위치 계산
|
|
69
|
+
let left = x + offsetX;
|
|
70
|
+
let top = y + offsetY;
|
|
71
|
+
// 화면 경계 확인 및 조정
|
|
72
|
+
const screenWidth = window.innerWidth;
|
|
73
|
+
const screenHeight = window.innerHeight;
|
|
74
|
+
if (left + tooltipWidth > screenWidth) {
|
|
75
|
+
left = x - tooltipWidth - offsetX;
|
|
76
|
+
}
|
|
77
|
+
if (top + tooltipHeight > screenHeight) {
|
|
78
|
+
top = y - tooltipHeight - offsetY;
|
|
79
|
+
}
|
|
80
|
+
// offsetParent 요소를 기준으로 위치 설정
|
|
81
|
+
if (this.offsetParent) {
|
|
82
|
+
const parentRect = this.offsetParent.getBoundingClientRect();
|
|
83
|
+
this.style.left = `${left - parentRect.left}px`;
|
|
84
|
+
this.style.top = `${top - parentRect.top}px`;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.style.left = `${left}px`;
|
|
88
|
+
this.style.top = `${top}px`;
|
|
89
|
+
const myRect = this.getBoundingClientRect();
|
|
90
|
+
/* 실제 바운드와 설정한 left/top 이 일치하지 않는다면, 부모 어딘가에서 transform 되었다고 판단하고, 보정해줌 */
|
|
91
|
+
if (myRect.left !== left || myRect.top !== top) {
|
|
92
|
+
this.style.left = `${left + (left - myRect.left)}px`;
|
|
93
|
+
this.style.top = `${top + (top - myRect.top)}px`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
this.setAttribute('visible', '');
|
|
97
|
+
}
|
|
98
|
+
hide() {
|
|
99
|
+
this.removeAttribute('visible');
|
|
100
|
+
}
|
|
101
|
+
render() {
|
|
102
|
+
return html `
|
|
103
|
+
<div class="title">${this.title}</div>
|
|
104
|
+
<div class="detail">
|
|
105
|
+
<span class="label">Type</span><span class="colon">:</span><span class="value">${this.type}</span>
|
|
106
|
+
<span class="label">Start Date</span><span class="colon">:</span><span class="value">${this.startDate}</span>
|
|
107
|
+
<span class="label">End Date</span><span class="colon">:</span><span class="value">${this.endDate}</span>
|
|
108
|
+
<span class="label">Progress</span><span class="colon">:</span><span class="value">${this.progress}%</span>
|
|
109
|
+
</div>
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
__decorate([
|
|
114
|
+
property({ type: String })
|
|
115
|
+
], OxTaskTooltip.prototype, "title", void 0);
|
|
116
|
+
__decorate([
|
|
117
|
+
property({ type: String })
|
|
118
|
+
], OxTaskTooltip.prototype, "startDate", void 0);
|
|
119
|
+
__decorate([
|
|
120
|
+
property({ type: String })
|
|
121
|
+
], OxTaskTooltip.prototype, "endDate", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
property({ type: Number })
|
|
124
|
+
], OxTaskTooltip.prototype, "progress", void 0);
|
|
125
|
+
__decorate([
|
|
126
|
+
property({ type: String })
|
|
127
|
+
], OxTaskTooltip.prototype, "type", void 0);
|
|
128
|
+
OxTaskTooltip = __decorate([
|
|
129
|
+
customElement('ox-task-tooltip')
|
|
130
|
+
], OxTaskTooltip);
|
|
131
|
+
export { OxTaskTooltip };
|
|
132
|
+
//# sourceMappingURL=ox-task-tooltip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-task-tooltip.js","sourceRoot":"","sources":["../../src/ox-task-tooltip.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGpD,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QAoDuB,UAAK,GAAG,EAAE,CAAA;QACV,cAAS,GAAG,EAAE,CAAA;QACd,YAAO,GAAG,EAAE,CAAA;QACZ,aAAQ,GAAG,CAAC,CAAA;QACZ,SAAI,GAAG,EAAE,CAAA;IA2DvC,CAAC;aAlHQ,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDlB,AAjDY,CAiDZ;IAQD,IAAI,CAAC,CAAS,EAAE,CAAS;QACvB,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAA;QACrC,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAA;QACvC,MAAM,OAAO,GAAG,EAAE,CAAA;QAClB,MAAM,OAAO,GAAG,EAAE,CAAA;QAElB,WAAW;QACX,IAAI,IAAI,GAAG,CAAC,GAAG,OAAO,CAAA;QACtB,IAAI,GAAG,GAAG,CAAC,GAAG,OAAO,CAAA;QAErB,gBAAgB;QAChB,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAA;QACrC,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAA;QAEvC,IAAI,IAAI,GAAG,YAAY,GAAG,WAAW,EAAE,CAAC;YACtC,IAAI,GAAG,CAAC,GAAG,YAAY,GAAG,OAAO,CAAA;QACnC,CAAC;QACD,IAAI,GAAG,GAAG,aAAa,GAAG,YAAY,EAAE,CAAC;YACvC,GAAG,GAAG,CAAC,GAAG,aAAa,GAAG,OAAO,CAAA;QACnC,CAAC;QAED,8BAA8B;QAC9B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAa,CAAC,qBAAqB,EAAE,CAAA;YAC7D,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,GAAG,UAAU,CAAC,IAAI,IAAI,CAAA;YAC/C,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,UAAU,CAAC,GAAG,IAAI,CAAA;QAC9C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,CAAA;YAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,CAAA;YAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAA;YAE3C,0EAA0E;YAC1E,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBAC/C,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;gBACpD,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAA;YAClD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,IAAI;QACF,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;2BACY,IAAI,CAAC,KAAK;;yFAEoD,IAAI,CAAC,IAAI;+FACH,IAAI,CAAC,SAAS;6FAChB,IAAI,CAAC,OAAO;6FACZ,IAAI,CAAC,QAAQ;;KAErG,CAAA;IACH,CAAC;;AA9D2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CAAW;AACV;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDAAe;AACd;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAa;AACZ;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAa;AACZ;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;2CAAU;AAxD1B,aAAa;IADzB,aAAa,CAAC,iBAAiB,CAAC;GACpB,aAAa,CAmHzB","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('ox-task-tooltip')\nexport class OxTaskTooltip extends LitElement {\n static styles = css`\n :host {\n position: fixed; /* position: absolute로 변경 */\n background-color: var(--ox-gantt-tooltip-background-color, var(--md-sys-color-surface, #f9f9f9));\n border: 1px solid var(--ox-gantt-tooltip-border-color, var(--md-sys-color-outline, #ccc));\n padding: var(--spacing-medium, 10px);\n border-radius: var(--spacing-medium, 8px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n visibility: hidden;\n z-index: 10;\n max-width: 300px;\n font-family: Roboto;\n font-size: 14px;\n line-height: 1.6;\n color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));\n transition:\n visibility 0.1s,\n opacity 0.1s;\n opacity: 0; /* 초기에는 보이지 않음 */\n }\n :host([visible]) {\n visibility: visible;\n opacity: 1; /* 보일 때는 불투명 */\n }\n .title {\n font-weight: bold;\n font-size: 16px;\n margin-bottom: 8px;\n color: var(--ox-gantt-tooltip-title-color, var(--md-sys-color-primary, #0078d4)); /* 파란색 텍스트 */\n }\n .detail {\n display: grid;\n grid-template-columns: auto auto 1fr;\n gap: 4px;\n align-items: center;\n }\n .label {\n font-weight: bold;\n color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface-variant, #333));\n text-align: right; /* 라벨을 우측 정렬 */\n }\n .colon {\n text-align: center;\n color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));\n }\n .value {\n text-align: left; /* 값을 좌측 정렬 */\n color: var(--ox-gantt-tooltip-color, var(--md-sys-color-on-surface, #333));\n }\n `\n\n @property({ type: String }) title = ''\n @property({ type: String }) startDate = ''\n @property({ type: String }) endDate = ''\n @property({ type: Number }) progress = 0\n @property({ type: String }) type = ''\n\n show(x: number, y: number) {\n const tooltipWidth = this.offsetWidth\n const tooltipHeight = this.offsetHeight\n const offsetX = 10\n const offsetY = 10\n\n // 기본 위치 계산\n let left = x + offsetX\n let top = y + offsetY\n\n // 화면 경계 확인 및 조정\n const screenWidth = window.innerWidth\n const screenHeight = window.innerHeight\n\n if (left + tooltipWidth > screenWidth) {\n left = x - tooltipWidth - offsetX\n }\n if (top + tooltipHeight > screenHeight) {\n top = y - tooltipHeight - offsetY\n }\n\n // offsetParent 요소를 기준으로 위치 설정\n if (this.offsetParent) {\n const parentRect = this.offsetParent!.getBoundingClientRect()\n this.style.left = `${left - parentRect.left}px`\n this.style.top = `${top - parentRect.top}px`\n } else {\n this.style.left = `${left}px`\n this.style.top = `${top}px`\n\n const myRect = this.getBoundingClientRect()\n\n /* 실제 바운드와 설정한 left/top 이 일치하지 않는다면, 부모 어딘가에서 transform 되었다고 판단하고, 보정해줌 */\n if (myRect.left !== left || myRect.top !== top) {\n this.style.left = `${left + (left - myRect.left)}px`\n this.style.top = `${top + (top - myRect.top)}px`\n }\n }\n\n this.setAttribute('visible', '')\n }\n\n hide() {\n this.removeAttribute('visible')\n }\n\n render() {\n return html`\n <div class=\"title\">${this.title}</div>\n <div class=\"detail\">\n <span class=\"label\">Type</span><span class=\"colon\">:</span><span class=\"value\">${this.type}</span>\n <span class=\"label\">Start Date</span><span class=\"colon\">:</span><span class=\"value\">${this.startDate}</span>\n <span class=\"label\">End Date</span><span class=\"colon\">:</span><span class=\"value\">${this.endDate}</span>\n <span class=\"label\">Progress</span><span class=\"colon\">:</span><span class=\"value\">${this.progress}%</span>\n </div>\n `\n }\n}\n"]}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export interface Task {
|
|
|
5
5
|
title: string;
|
|
6
6
|
type: TaskType;
|
|
7
7
|
section?: Section;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
startDate: Date;
|
|
9
|
+
endDate: Date;
|
|
10
10
|
progress?: number;
|
|
11
|
-
|
|
11
|
+
dependsOn?: string;
|
|
12
12
|
length: string;
|
|
13
13
|
tags?: TaskTag[];
|
|
14
14
|
children?: Task[];
|
|
@@ -16,4 +16,11 @@ export interface Task {
|
|
|
16
16
|
export interface Section {
|
|
17
17
|
name: string;
|
|
18
18
|
}
|
|
19
|
+
export interface ColumnConfig {
|
|
20
|
+
name: string;
|
|
21
|
+
label: string;
|
|
22
|
+
visible: boolean;
|
|
23
|
+
width: string;
|
|
24
|
+
order: number;
|
|
25
|
+
}
|
|
19
26
|
export type LEVEL = 'year-quarter' | 'year-month' | 'quarter-week' | 'week-day';
|
package/dist/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type TaskTag = 'done' | 'active' | 'critical' | 'milestone'\nexport type TaskType = 'task' | 'milestone' | 'phase'\n\nexport interface Task {\n id: string\n title: string\n type: TaskType\n section?: Section\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type TaskTag = 'done' | 'active' | 'critical' | 'milestone'\nexport type TaskType = 'task' | 'milestone' | 'phase'\n\nexport interface Task {\n id: string\n title: string\n type: TaskType\n section?: Section\n startDate: Date\n endDate: Date\n progress?: number\n dependsOn?: string // 이전 태스크의 ID\n length: string // 예: '3d' (3 days)\n tags?: TaskTag[]\n children?: Task[]\n}\n\nexport interface Section {\n name: string\n}\n\nexport interface ColumnConfig {\n name: string\n label: string\n visible: boolean\n width: string\n order: number\n}\n\nexport type LEVEL = 'year-quarter' | 'year-month' | 'quarter-week' | 'week-day'\n"]}
|