@sequent-org/moodboard 1.2.50 → 1.2.51

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sequent-org/moodboard",
3
- "version": "1.2.50",
3
+ "version": "1.2.51",
4
4
  "type": "module",
5
5
  "description": "Interactive moodboard",
6
6
  "main": "./src/index.js",
@@ -42,8 +42,12 @@ export class ApiClient {
42
42
 
43
43
  async saveBoard(boardId, boardData) {
44
44
  try {
45
+ // Поддержка нового формата: { boardData: {...}, settings: {...} }
46
+ let payloadBoardData = boardData && boardData.boardData ? boardData.boardData : boardData;
47
+ let payloadSettings = boardData && boardData.settings ? boardData.settings : undefined;
48
+
45
49
  // Фильтруем объекты изображений и файлов - убираем избыточные данные
46
- const cleanedData = this._cleanObjectData(boardData);
50
+ const cleanedData = this._cleanObjectData(payloadBoardData);
47
51
 
48
52
  const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
49
53
 
@@ -58,7 +62,8 @@ export class ApiClient {
58
62
  credentials: 'same-origin',
59
63
  body: JSON.stringify({
60
64
  boardId: boardId,
61
- boardData: cleanedData
65
+ boardData: cleanedData,
66
+ settings: payloadSettings
62
67
  })
63
68
  });
64
69
 
package/src/core/index.js CHANGED
@@ -2151,7 +2151,52 @@ export class CoreMoodBoard {
2151
2151
  * Получение данных доски для сохранения
2152
2152
  */
2153
2153
  getBoardData() {
2154
- return this.state.serialize();
2154
+ // Базовые данные доски (объекты и метаданные из state)
2155
+ const s = this.state.serialize();
2156
+ const boardData = {
2157
+ objects: Array.isArray(s.objects) ? s.objects : [],
2158
+ name: s.name || s.title || 'Untitled Board',
2159
+ description: s.description || null
2160
+ };
2161
+
2162
+ // Настройки (settings): фон, сетка, зум, размеры канваса
2163
+ const app = this.pixi?.app;
2164
+ const rendererBg = app?.renderer?.background?.color ?? app?.renderer?.backgroundColor;
2165
+ const toHex = (num) => {
2166
+ try { return '#' + Number(num >>> 0).toString(16).padStart(6, '0'); } catch (_) { return '#F5F5F5'; }
2167
+ };
2168
+ const world = this.pixi?.worldLayer || app?.stage;
2169
+ const currentZoom = Math.max(0.1, Math.min(5, world?.scale?.x || 1));
2170
+ const canvasW = app?.view?.clientWidth || app?.view?.width || 0;
2171
+ const canvasH = app?.view?.clientHeight || app?.view?.height || 0;
2172
+
2173
+ // Сетка: берём то, что накапливается в state.board.grid через BoardService
2174
+ const gridState = (this.state?.state?.board && this.state.state.board.grid) ? this.state.state.board.grid : null;
2175
+ const gridSettings = (() => {
2176
+ if (gridState && gridState.type) {
2177
+ // Если храним полные options от serialize(), извлекаем ключевые
2178
+ const opts = gridState.options || {};
2179
+ // Унификация ключей под формат из задачи
2180
+ return {
2181
+ type: gridState.type,
2182
+ size: opts.size || 20,
2183
+ visible: opts.enabled !== false,
2184
+ color: toHex(opts.color ?? 0xE0E0E0)
2185
+ };
2186
+ }
2187
+ return null;
2188
+ })();
2189
+
2190
+ const settings = {
2191
+ backgroundColor: toHex(rendererBg ?? 0xF5F5F5),
2192
+ grid: gridSettings || undefined,
2193
+ zoom: { min: 0.1, max: 5.0, default: 1.0, current: currentZoom },
2194
+ canvas: { width: canvasW, height: canvasH }
2195
+ };
2196
+
2197
+ const boardId = (this.state?.state?.board && this.state.state.board.id) || this.options?.boardId || null;
2198
+
2199
+ return { id: boardId, boardData, settings };
2155
2200
  }
2156
2201
 
2157
2202
  /**
@@ -19,7 +19,7 @@ export class DataManager {
19
19
 
20
20
  // Восстанавливаем тип сетки и её параметры до загрузки объектов
21
21
  try {
22
- const grid = data.grid || (data.board && data.board.grid);
22
+ const grid = (data.settings && data.settings.grid) || data.grid || (data.board && data.board.grid);
23
23
  if (grid && grid.type) {
24
24
  const payload = { type: grid.type };
25
25
  const opts = grid.options || null;
@@ -29,6 +29,36 @@ export class DataManager {
29
29
  this.coreMoodboard.eventBus.emit(this.coreMoodboard.Events?.UI?.GridChange || 'ui:grid:change', payload);
30
30
  }
31
31
  } catch (_) {}
32
+
33
+ // Восстановим фон и зум из settings, если есть
34
+ try {
35
+ const settings = data.settings || {};
36
+ // Фон
37
+ const bg = settings.backgroundColor;
38
+ if (bg && this.coreMoodboard?.pixi?.app?.renderer) {
39
+ const parseHex = (v) => {
40
+ if (typeof v === 'number') return v;
41
+ if (typeof v === 'string') {
42
+ const s = v.startsWith('#') ? v.slice(1) : v;
43
+ const n = parseInt(s, 16);
44
+ if (Number.isFinite(n)) return n;
45
+ }
46
+ return null;
47
+ };
48
+ const bgInt = parseHex(bg);
49
+ if (bgInt != null) this.coreMoodboard.pixi.app.renderer.backgroundColor = bgInt;
50
+ }
51
+ // Зум
52
+ const z = settings.zoom && (settings.zoom.current || settings.zoom.default);
53
+ const world = this.coreMoodboard?.pixi?.worldLayer || this.coreMoodboard?.pixi?.app?.stage;
54
+ if (world && Number.isFinite(z) && z > 0) {
55
+ world.scale.set(z);
56
+ const percent = Math.round(z * 100);
57
+ try {
58
+ this.coreMoodboard.eventBus.emit('ui:zoom:percent', { percentage: percent });
59
+ } catch (_) {}
60
+ }
61
+ } catch (_) {}
32
62
 
33
63
  // Загружаем объекты
34
64
  if (data.objects && Array.isArray(data.objects)) {