@sequent-org/moodboard 1.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/package.json +44 -0
- package/src/assets/icons/README.md +105 -0
- package/src/assets/icons/attachments.svg +3 -0
- package/src/assets/icons/clear.svg +5 -0
- package/src/assets/icons/comments.svg +3 -0
- package/src/assets/icons/emoji.svg +6 -0
- package/src/assets/icons/frame.svg +3 -0
- package/src/assets/icons/image.svg +3 -0
- package/src/assets/icons/note.svg +3 -0
- package/src/assets/icons/pan.svg +3 -0
- package/src/assets/icons/pencil.svg +3 -0
- package/src/assets/icons/redo.svg +3 -0
- package/src/assets/icons/select.svg +9 -0
- package/src/assets/icons/shapes.svg +3 -0
- package/src/assets/icons/text-add.svg +3 -0
- package/src/assets/icons/topbar/README.md +39 -0
- package/src/assets/icons/topbar/grid-cross.svg +6 -0
- package/src/assets/icons/topbar/grid-dot.svg +3 -0
- package/src/assets/icons/topbar/grid-line.svg +3 -0
- package/src/assets/icons/topbar/grid-off.svg +3 -0
- package/src/assets/icons/topbar/paint.svg +3 -0
- package/src/assets/icons/undo.svg +3 -0
- package/src/core/ApiClient.js +309 -0
- package/src/core/EventBus.js +42 -0
- package/src/core/HistoryManager.js +261 -0
- package/src/core/KeyboardManager.js +710 -0
- package/src/core/PixiEngine.js +439 -0
- package/src/core/SaveManager.js +381 -0
- package/src/core/StateManager.js +64 -0
- package/src/core/commands/BaseCommand.js +68 -0
- package/src/core/commands/CopyObjectCommand.js +44 -0
- package/src/core/commands/CreateObjectCommand.js +46 -0
- package/src/core/commands/DeleteObjectCommand.js +146 -0
- package/src/core/commands/EditFileNameCommand.js +107 -0
- package/src/core/commands/GroupMoveCommand.js +47 -0
- package/src/core/commands/GroupReorderZCommand.js +74 -0
- package/src/core/commands/GroupResizeCommand.js +37 -0
- package/src/core/commands/GroupRotateCommand.js +41 -0
- package/src/core/commands/MoveObjectCommand.js +89 -0
- package/src/core/commands/PasteObjectCommand.js +103 -0
- package/src/core/commands/ReorderZCommand.js +45 -0
- package/src/core/commands/ResizeObjectCommand.js +135 -0
- package/src/core/commands/RotateObjectCommand.js +70 -0
- package/src/core/commands/index.js +14 -0
- package/src/core/events/Events.js +147 -0
- package/src/core/index.js +1632 -0
- package/src/core/rendering/GeometryUtils.js +89 -0
- package/src/core/rendering/HitTestManager.js +186 -0
- package/src/core/rendering/LayerManager.js +137 -0
- package/src/core/rendering/ObjectRenderer.js +363 -0
- package/src/core/rendering/PixiRenderer.js +140 -0
- package/src/core/rendering/index.js +9 -0
- package/src/grid/BaseGrid.js +164 -0
- package/src/grid/CrossGrid.js +75 -0
- package/src/grid/DotGrid.js +148 -0
- package/src/grid/GridFactory.js +173 -0
- package/src/grid/LineGrid.js +115 -0
- package/src/index.js +2 -0
- package/src/moodboard/ActionHandler.js +114 -0
- package/src/moodboard/DataManager.js +114 -0
- package/src/moodboard/MoodBoard.js +359 -0
- package/src/moodboard/WorkspaceManager.js +103 -0
- package/src/objects/BaseObject.js +1 -0
- package/src/objects/CommentObject.js +115 -0
- package/src/objects/DrawingObject.js +114 -0
- package/src/objects/EmojiObject.js +98 -0
- package/src/objects/FileObject.js +318 -0
- package/src/objects/FrameObject.js +127 -0
- package/src/objects/ImageObject.js +72 -0
- package/src/objects/NoteObject.js +227 -0
- package/src/objects/ObjectFactory.js +61 -0
- package/src/objects/ShapeObject.js +134 -0
- package/src/objects/StampObject.js +0 -0
- package/src/objects/StickerObject.js +0 -0
- package/src/objects/TextObject.js +123 -0
- package/src/services/BoardService.js +85 -0
- package/src/services/FileUploadService.js +398 -0
- package/src/services/FrameService.js +138 -0
- package/src/services/ImageUploadService.js +246 -0
- package/src/services/ZOrderManager.js +50 -0
- package/src/services/ZoomPanController.js +78 -0
- package/src/src.7z +0 -0
- package/src/src.zip +0 -0
- package/src/src2.zip +0 -0
- package/src/tools/AlignmentGuides.js +326 -0
- package/src/tools/BaseTool.js +257 -0
- package/src/tools/ResizeHandles.js +381 -0
- package/src/tools/ToolManager.js +580 -0
- package/src/tools/board-tools/PanTool.js +43 -0
- package/src/tools/board-tools/ZoomTool.js +393 -0
- package/src/tools/object-tools/DrawingTool.js +404 -0
- package/src/tools/object-tools/PlacementTool.js +1005 -0
- package/src/tools/object-tools/SelectTool.js +2183 -0
- package/src/tools/object-tools/TextTool.js +416 -0
- package/src/tools/object-tools/selection/BoxSelectController.js +105 -0
- package/src/tools/object-tools/selection/GeometryUtils.js +101 -0
- package/src/tools/object-tools/selection/GroupDragController.js +61 -0
- package/src/tools/object-tools/selection/GroupResizeController.js +90 -0
- package/src/tools/object-tools/selection/GroupRotateController.js +61 -0
- package/src/tools/object-tools/selection/HandlesSync.js +96 -0
- package/src/tools/object-tools/selection/ResizeController.js +68 -0
- package/src/tools/object-tools/selection/RotateController.js +58 -0
- package/src/tools/object-tools/selection/SelectionModel.js +42 -0
- package/src/tools/object-tools/selection/SimpleDragController.js +45 -0
- package/src/ui/CommentPopover.js +187 -0
- package/src/ui/ContextMenu.js +340 -0
- package/src/ui/FilePropertiesPanel.js +298 -0
- package/src/ui/FramePropertiesPanel.js +462 -0
- package/src/ui/HtmlHandlesLayer.js +778 -0
- package/src/ui/HtmlTextLayer.js +279 -0
- package/src/ui/MapPanel.js +290 -0
- package/src/ui/NotePropertiesPanel.js +502 -0
- package/src/ui/SaveStatus.js +250 -0
- package/src/ui/TextPropertiesPanel.js +911 -0
- package/src/ui/Toolbar.js +1118 -0
- package/src/ui/Topbar.js +220 -0
- package/src/ui/ZoomPanel.js +116 -0
- package/src/ui/styles/workspace.css +854 -0
- package/src/utils/colors.js +0 -0
- package/src/utils/geometry.js +0 -0
- package/src/utils/iconLoader.js +270 -0
- package/src/utils/objectIdGenerator.js +17 -0
- package/src/utils/topbarIconLoader.js +114 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Компонент индикатора статуса сохранения
|
|
3
|
+
*/
|
|
4
|
+
import { Events } from '../core/events/Events.js';
|
|
5
|
+
|
|
6
|
+
export class SaveStatus {
|
|
7
|
+
constructor(container, eventBus, options = {}) {
|
|
8
|
+
this.container = container;
|
|
9
|
+
this.eventBus = eventBus;
|
|
10
|
+
this.options = {
|
|
11
|
+
// Фиксированные настройки UI (оптимальные для пользователя)
|
|
12
|
+
showTimestamp: true,
|
|
13
|
+
autoHide: true,
|
|
14
|
+
hideDelay: 3000,
|
|
15
|
+
position: 'bottom-left',
|
|
16
|
+
// Настраиваемые опции (только для внутреннего использования)
|
|
17
|
+
...options
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
this.element = null;
|
|
21
|
+
this.hideTimer = null;
|
|
22
|
+
|
|
23
|
+
this.init();
|
|
24
|
+
this.setupEventListeners();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Инициализация UI элемента
|
|
29
|
+
*/
|
|
30
|
+
init() {
|
|
31
|
+
this.element = document.createElement('div');
|
|
32
|
+
this.element.className = this.getBaseClasses();
|
|
33
|
+
this.element.innerHTML = this.getInitialContent();
|
|
34
|
+
|
|
35
|
+
// Позиционирование
|
|
36
|
+
this.applyPositioning();
|
|
37
|
+
|
|
38
|
+
// Добавляем в контейнер
|
|
39
|
+
this.container.appendChild(this.element);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Получение базовых CSS классов
|
|
44
|
+
*/
|
|
45
|
+
getBaseClasses() {
|
|
46
|
+
return [
|
|
47
|
+
'moodboard-save-status',
|
|
48
|
+
'absolute'
|
|
49
|
+
].join(' ');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Применение позиционирования
|
|
54
|
+
*/
|
|
55
|
+
applyPositioning() {
|
|
56
|
+
const positions = {
|
|
57
|
+
'top-left': { top: '12px', left: '12px' },
|
|
58
|
+
'top-right': { top: '12px', right: '12px' },
|
|
59
|
+
'bottom-left': { bottom: '12px', left: '12px' },
|
|
60
|
+
'bottom-right': { bottom: '12px', right: '12px' }
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const pos = positions[this.options.position] || positions['top-right'];
|
|
64
|
+
|
|
65
|
+
Object.assign(this.element.style, pos);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Начальный контент
|
|
70
|
+
*/
|
|
71
|
+
getInitialContent() {
|
|
72
|
+
return `
|
|
73
|
+
<div class="save-textline">
|
|
74
|
+
<span class="save-text">Готов к работе</span>
|
|
75
|
+
${this.options.showTimestamp ? '<span class="save-time"></span>' : ''}
|
|
76
|
+
</div>
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Настройка обработчиков событий
|
|
82
|
+
*/
|
|
83
|
+
setupEventListeners() {
|
|
84
|
+
// Статус сохранения
|
|
85
|
+
this.eventBus.on(Events.Save.StatusChanged, (data) => {
|
|
86
|
+
this.updateStatus(data);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Успешное сохранение
|
|
90
|
+
this.eventBus.on(Events.Save.Success, (data) => {
|
|
91
|
+
this.showSuccess(data);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Ошибка сохранения
|
|
95
|
+
this.eventBus.on(Events.Save.Error, (data) => {
|
|
96
|
+
this.showError(data);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Обновление статуса
|
|
102
|
+
*/
|
|
103
|
+
updateStatus(data) {
|
|
104
|
+
const iconEl = this.element.querySelector('.save-icon');
|
|
105
|
+
const textEl = this.element.querySelector('.save-text');
|
|
106
|
+
const timeEl = this.element.querySelector('.save-time');
|
|
107
|
+
|
|
108
|
+
// Очищаем предыдущий таймер
|
|
109
|
+
if (this.hideTimer) {
|
|
110
|
+
clearTimeout(this.hideTimer);
|
|
111
|
+
this.hideTimer = null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Показываем элемент
|
|
115
|
+
this.element.style.opacity = '1';
|
|
116
|
+
|
|
117
|
+
switch (data.status) {
|
|
118
|
+
case 'pending':
|
|
119
|
+
this.applyStyle('pending');
|
|
120
|
+
textEl.textContent = 'Изменения...';
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
case 'saving':
|
|
124
|
+
this.applyStyle('saving');
|
|
125
|
+
textEl.textContent = 'Сохранение...';
|
|
126
|
+
break;
|
|
127
|
+
|
|
128
|
+
case 'saved':
|
|
129
|
+
this.applyStyle('saved');
|
|
130
|
+
textEl.textContent = 'Сохранено';
|
|
131
|
+
this.scheduleAutoHide();
|
|
132
|
+
break;
|
|
133
|
+
|
|
134
|
+
case 'error':
|
|
135
|
+
this.applyStyle('error');
|
|
136
|
+
textEl.textContent = data.message || 'Ошибка сохранения';
|
|
137
|
+
this.scheduleAutoHide(6000); // Ошибки показываем дольше
|
|
138
|
+
break;
|
|
139
|
+
|
|
140
|
+
default:
|
|
141
|
+
this.applyStyle('idle');
|
|
142
|
+
textEl.textContent = 'Готов к работе';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Обновляем время
|
|
146
|
+
if (timeEl && this.options.showTimestamp) {
|
|
147
|
+
const time = new Date().toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
|
|
148
|
+
timeEl.textContent = time;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Применение стилей для статуса
|
|
154
|
+
*/
|
|
155
|
+
applyStyle(status) {
|
|
156
|
+
// Плоский стиль без цветной подложки
|
|
157
|
+
this.element.className = 'moodboard-save-status absolute';
|
|
158
|
+
this.element.style.background = 'transparent';
|
|
159
|
+
this.element.style.border = 'none';
|
|
160
|
+
this.element.style.boxShadow = 'none';
|
|
161
|
+
this.element.style.padding = '0';
|
|
162
|
+
this.element.style.transform = 'none';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Показать успешное сохранение
|
|
167
|
+
*/
|
|
168
|
+
showSuccess(data) {
|
|
169
|
+
// Дополнительные действия при успешном сохранении
|
|
170
|
+
if (data.timestamp && this.options.showTimestamp) {
|
|
171
|
+
console.log('Данные сохранены в:', data.timestamp);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Показать ошибку
|
|
177
|
+
*/
|
|
178
|
+
showError(data) {
|
|
179
|
+
// Дополнительные действия при ошибке
|
|
180
|
+
console.error('Ошибка сохранения:', data.error);
|
|
181
|
+
|
|
182
|
+
// Можно добавить звуковое уведомление или другие действия
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Запланировать автоскрытие
|
|
187
|
+
*/
|
|
188
|
+
scheduleAutoHide(delay = null) {
|
|
189
|
+
if (!this.options.autoHide) return;
|
|
190
|
+
|
|
191
|
+
const hideDelay = delay || this.options.hideDelay;
|
|
192
|
+
|
|
193
|
+
this.hideTimer = setTimeout(() => {
|
|
194
|
+
this.element.style.opacity = '0.6';
|
|
195
|
+
}, hideDelay);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Принудительное скрытие
|
|
200
|
+
*/
|
|
201
|
+
hide() {
|
|
202
|
+
this.element.style.opacity = '0';
|
|
203
|
+
this.element.style.transform = 'translateY(-20px)';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Принудительное показывание
|
|
208
|
+
*/
|
|
209
|
+
show() {
|
|
210
|
+
this.element.style.opacity = '1';
|
|
211
|
+
this.element.style.transform = 'translateY(0)';
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Обновление позиции
|
|
216
|
+
*/
|
|
217
|
+
setPosition(position) {
|
|
218
|
+
this.options.position = position;
|
|
219
|
+
this.applyPositioning();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Получение текущего статуса
|
|
224
|
+
*/
|
|
225
|
+
getCurrentStatus() {
|
|
226
|
+
const classList = this.element.className;
|
|
227
|
+
if (classList.includes('status-saving')) return 'saving';
|
|
228
|
+
if (classList.includes('status-saved')) return 'saved';
|
|
229
|
+
if (classList.includes('status-error')) return 'error';
|
|
230
|
+
if (classList.includes('status-pending')) return 'pending';
|
|
231
|
+
return 'idle';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Очистка ресурсов
|
|
236
|
+
*/
|
|
237
|
+
destroy() {
|
|
238
|
+
if (this.hideTimer) {
|
|
239
|
+
clearTimeout(this.hideTimer);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this.eventBus.off(Events.Save.StatusChanged);
|
|
243
|
+
this.eventBus.off(Events.Save.Success);
|
|
244
|
+
this.eventBus.off(Events.Save.Error);
|
|
245
|
+
|
|
246
|
+
if (this.element && this.element.parentNode) {
|
|
247
|
+
this.element.parentNode.removeChild(this.element);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|