@sequent-org/moodboard 1.2.54 → 1.2.56
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 +1 -1
- package/src/ui/Topbar.js +61 -21
package/package.json
CHANGED
package/src/ui/Topbar.js
CHANGED
|
@@ -11,6 +11,7 @@ export class Topbar {
|
|
|
11
11
|
this.theme = theme;
|
|
12
12
|
this.element = null;
|
|
13
13
|
this._paintPopover = null;
|
|
14
|
+
this._currentBoardHex = null; // фактический цвет фона доски (#rrggbb)
|
|
14
15
|
// Загружаем иконки
|
|
15
16
|
this.iconLoader = new TopbarIconLoader();
|
|
16
17
|
this.icons = this.iconLoader.icons;
|
|
@@ -42,18 +43,31 @@ export class Topbar {
|
|
|
42
43
|
this.setActive(type);
|
|
43
44
|
});
|
|
44
45
|
|
|
45
|
-
// Обновляем цвет кнопки "краски" при выборе цвета фона
|
|
46
|
-
this.eventBus.on(Events.UI.PaintPick, ({ btnHex }) => {
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// Обновляем цвет кнопки "краски" и текущий board-hex при выборе цвета фона
|
|
47
|
+
this.eventBus.on(Events.UI.PaintPick, ({ btnHex, color }) => {
|
|
48
|
+
// color — фактический цвет фона доски (может быть #rrggbb или number)
|
|
49
|
+
const normalizeHex = (v) => {
|
|
50
|
+
if (!v) return null;
|
|
51
|
+
if (typeof v === 'number') {
|
|
52
|
+
return `#${v.toString(16).padStart(6,'0')}`.toLowerCase();
|
|
53
|
+
}
|
|
54
|
+
if (typeof v === 'string') {
|
|
55
|
+
const s = v.startsWith('#') ? v : `#${v}`;
|
|
56
|
+
return s.toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
60
|
+
const boardHex = normalizeHex(color);
|
|
61
|
+
if (boardHex) this._currentBoardHex = boardHex;
|
|
62
|
+
const mapped = btnHex || this.mapBoardToBtnHex(boardHex);
|
|
63
|
+
if (mapped) this.setPaintButtonHex(mapped);
|
|
49
64
|
});
|
|
50
65
|
|
|
51
66
|
// Инициализация цвета кнопки "краска" из текущего фона доски, если доступен
|
|
52
67
|
try {
|
|
53
68
|
const bgHex = this._getCurrentBoardBackgroundHex();
|
|
54
69
|
if (bgHex) {
|
|
55
|
-
|
|
56
|
-
this.setPaintButtonHex(mapped);
|
|
70
|
+
this.setCurrentBoardHex(bgHex);
|
|
57
71
|
}
|
|
58
72
|
} catch (_) {}
|
|
59
73
|
}
|
|
@@ -201,6 +215,15 @@ export class Topbar {
|
|
|
201
215
|
}
|
|
202
216
|
}
|
|
203
217
|
|
|
218
|
+
/** Задать текущий фактический цвет фона и синхронизировать кнопку */
|
|
219
|
+
setCurrentBoardHex(boardHex) {
|
|
220
|
+
if (!boardHex) return;
|
|
221
|
+
const v = String(boardHex).toLowerCase();
|
|
222
|
+
this._currentBoardHex = v.startsWith('#') ? v : `#${v}`;
|
|
223
|
+
const mapped = this.mapBoardToBtnHex(this._currentBoardHex) || this._currentBoardHex;
|
|
224
|
+
this.setPaintButtonHex(mapped);
|
|
225
|
+
}
|
|
226
|
+
|
|
204
227
|
setActive(type) {
|
|
205
228
|
const buttons = this.element.querySelectorAll('.moodboard-topbar__button');
|
|
206
229
|
buttons.forEach((b) => b.classList.remove('moodboard-topbar__button--active'));
|
|
@@ -253,8 +276,9 @@ export class Topbar {
|
|
|
253
276
|
b.style.borderColor = darken(c.hex, 0.35);
|
|
254
277
|
// Цвет галочки — чёрный для максимальной видимости
|
|
255
278
|
b.style.color = '#111';
|
|
256
|
-
// Для надёжного сравнения — сохраняем
|
|
257
|
-
b.dataset.hex = String(c.hex).toLowerCase();
|
|
279
|
+
// Для надёжного сравнения — сохраняем оба значения в dataset
|
|
280
|
+
b.dataset.hex = String(c.hex).toLowerCase(); // цвет кружка-кнопки
|
|
281
|
+
b.dataset.board = String(c.board).toLowerCase(); // фактический цвет фона доски
|
|
258
282
|
// Галочка по центру
|
|
259
283
|
const tick = document.createElement('i');
|
|
260
284
|
tick.className = 'moodboard-topbar__paint-tick';
|
|
@@ -277,21 +301,37 @@ export class Topbar {
|
|
|
277
301
|
});
|
|
278
302
|
pop.appendChild(grid);
|
|
279
303
|
|
|
280
|
-
// Выделяем активный цвет галочкой (надежно — по data-
|
|
304
|
+
// Выделяем активный цвет галочкой (надежно — по data-board, с fallback ближайшего)
|
|
281
305
|
try {
|
|
282
|
-
//
|
|
283
|
-
const
|
|
284
|
-
//
|
|
285
|
-
let
|
|
286
|
-
//
|
|
287
|
-
if (!
|
|
288
|
-
const
|
|
289
|
-
|
|
306
|
+
// Текущий цвет фона доски (#rrggbb)
|
|
307
|
+
const currentBoardHex = (this._currentBoardHex || this._getCurrentBoardBackgroundHex() || '').toLowerCase();
|
|
308
|
+
// Пытаемся найти точное совпадение по data-board
|
|
309
|
+
let match = currentBoardHex ? grid.querySelector(`[data-board="${currentBoardHex}"]`) : null;
|
|
310
|
+
// Если точного совпадения нет — выбираем ближайший по евклидовой дистанции в RGB
|
|
311
|
+
if (!match) {
|
|
312
|
+
const hexToRgb = (hex) => {
|
|
313
|
+
try {
|
|
314
|
+
const h = hex.replace('#','');
|
|
315
|
+
return {
|
|
316
|
+
r: parseInt(h.substring(0,2), 16),
|
|
317
|
+
g: parseInt(h.substring(2,4), 16),
|
|
318
|
+
b: parseInt(h.substring(4,6), 16)
|
|
319
|
+
};
|
|
320
|
+
} catch (_) { return { r: 0, g: 0, b: 0 }; }
|
|
321
|
+
};
|
|
322
|
+
const dist2 = (a, b) => {
|
|
323
|
+
const dr = a.r - b.r, dg = a.g - b.g, db = a.b - b.b;
|
|
324
|
+
return dr*dr + dg*dg + db*db;
|
|
325
|
+
};
|
|
326
|
+
const target = hexToRgb(currentBoardHex || '#f7fbff');
|
|
327
|
+
let best = null, bestD = Infinity;
|
|
328
|
+
Array.from(grid.children).forEach((el) => {
|
|
329
|
+
const boardHex = el.dataset.board || '';
|
|
330
|
+
const d = dist2(target, hexToRgb(boardHex));
|
|
331
|
+
if (d < bestD) { bestD = d; best = el; }
|
|
332
|
+
});
|
|
333
|
+
match = best;
|
|
290
334
|
}
|
|
291
|
-
// 4) Фолбэк — первый цвет из палитры
|
|
292
|
-
if (!targetHex) targetHex = '#B3E5FC';
|
|
293
|
-
const normalized = String(targetHex).trim().toLowerCase();
|
|
294
|
-
const match = grid.querySelector(`[data-hex="${normalized}"]`);
|
|
295
335
|
if (match) match.classList.add('is-active');
|
|
296
336
|
} catch (_) {}
|
|
297
337
|
|