@sequent-org/moodboard 1.0.20 → 1.0.22

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.0.20",
3
+ "version": "1.0.22",
4
4
  "type": "module",
5
5
  "description": "Interactive moodboard",
6
6
  "main": "./src/index.js",
@@ -201,19 +201,20 @@
201
201
  display: inline-flex;
202
202
  align-items: center;
203
203
  justify-content: center;
204
- width: 40px;
205
- height: 40px;
204
+ width: 30px;
205
+ height: 30px;
206
206
  border: none;
207
207
  border-radius: 8px;
208
208
  /* background: #E1F5FE; */
209
209
  /* color: #212121; */
210
+ background: none;
210
211
  font-size: 18px;
211
212
  font-weight: 500;
212
213
  cursor: pointer;
213
214
  transition: all 0.2s ease;
214
215
  text-align: center;
215
216
  position: relative;
216
- margin: 2px;
217
+ margin: 0px;
217
218
  }
218
219
 
219
220
  .moodboard-toolbar__button:hover {
@@ -1,77 +1,53 @@
1
1
  /**
2
2
  * Загрузчик SVG иконок для верхней панели
3
+ * Работает точно так же как IconLoader для левой панели
3
4
  */
4
5
  export class TopbarIconLoader {
5
6
  constructor() {
6
- this.icons = new Map();
7
- this.init();
7
+ this.cache = new Map();
8
+ this.icons = {};
8
9
  }
9
10
 
11
+ /**
12
+ * Инициализирует иконки при создании экземпляра
13
+ */
10
14
  async init() {
15
+ // Импортируем все SVG файлы статически, как в IconLoader
11
16
  try {
12
- // Сначала загружаем встроенные иконки как основной источник
13
- this.loadBuiltInIcons();
14
-
15
- // Затем пытаемся загрузить из файлов (если доступно)
16
- await this.loadTopbarIcons();
17
-
18
- console.log('✅ Иконки верхней панели загружены успешно');
19
-
20
- } catch (error) {
21
- console.error('❌ Критическая ошибка загрузки иконок верхней панели:', error);
22
- // В случае ошибки у нас уже есть встроенные иконки
23
- }
24
- }
17
+ // Используем динамический импорт для всех иконок topbar
18
+ const iconModules = await Promise.all([
19
+ import('../assets/icons/grid-line.svg?raw'),
20
+ import('../assets/icons/grid-dot.svg?raw'),
21
+ import('../assets/icons/grid-cross.svg?raw'),
22
+ import('../assets/icons/grid-off.svg?raw'),
23
+ import('../assets/icons/paint.svg?raw')
24
+ ]);
25
25
 
26
- async loadTopbarIcons() {
27
- // Список иконок, которые нужно загрузить
28
- const iconNames = ['grid-line', 'grid-dot', 'grid-cross', 'grid-off', 'paint'];
29
-
30
- for (const iconName of iconNames) {
31
- try {
32
- const svgContent = await this.loadIconFromFile(iconName);
33
- if (svgContent) {
34
- this.icons.set(iconName, svgContent);
35
- console.log(`✅ Загружена иконка из файла: ${iconName}`);
36
- }
37
- } catch (error) {
38
- console.warn(`⚠️ Не удалось загрузить иконку ${iconName} из файла:`, error.message);
39
- // Оставляем встроенную версию
40
- }
41
- }
42
-
43
- console.log(`📦 Всего загружено ${this.icons.size} иконок верхней панели`);
44
- }
26
+ // Сохраняем иконки в кэш
27
+ const iconNames = ['grid-line', 'grid-dot', 'grid-cross', 'grid-off', 'paint'];
45
28
 
46
- async loadIconFromFile(iconName) {
47
- // Пробуем несколько способов загрузки для разных окружений
48
- const paths = [
49
- `/src/assets/icons/topbar/${iconName}.svg`,
50
- `./src/assets/icons/topbar/${iconName}.svg`,
51
- `../assets/icons/topbar/${iconName}.svg`,
52
- `assets/icons/topbar/${iconName}.svg`,
53
- `/assets/icons/topbar/${iconName}.svg`
54
- ];
55
-
56
- for (const path of paths) {
57
- try {
58
- const response = await fetch(path);
59
- if (response.ok) {
60
- const svgContent = await response.text();
61
- console.log(`✅ Иконка ${iconName} загружена с пути: ${path}`);
62
- return svgContent;
29
+ iconNames.forEach((name, index) => {
30
+ if (iconModules[index] && iconModules[index].default) {
31
+ this.icons[name] = iconModules[index].default;
32
+ this.cache.set(name, iconModules[index].default);
33
+ } else {
34
+ console.warn(`⚠️ Иконка ${name} не загружена, используем fallback`);
35
+ this.icons[name] = this.getFallbackIcon(name);
63
36
  }
64
- } catch (error) {
65
- console.warn(`⚠️ Не удалось загрузить ${iconName} с пути ${path}:`, error.message);
66
- continue;
67
- }
37
+ });
38
+
39
+ } catch (error) {
40
+ console.error('❌ Ошибка статической загрузки иконок topbar:', error);
41
+ console.log('🔄 Пробуем загрузить встроенные SVG иконки...');
42
+ // В случае ошибки загружаем встроенные SVG иконки
43
+ this.loadBuiltInIcons();
68
44
  }
69
-
70
- return null; // Возвращаем null вместо ошибки
71
45
  }
72
46
 
73
- getBuiltInIcon(iconName) {
74
- // Встроенные иконки как основной источник
47
+ /**
48
+ * Загружает встроенные SVG иконки (резервный метод)
49
+ */
50
+ loadBuiltInIcons() {
75
51
  const builtInIcons = {
76
52
  'grid-line': `<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
77
53
  <path d="M2 2H16V4H2V2Z" fill="currentColor"/>
@@ -119,44 +95,114 @@ export class TopbarIconLoader {
119
95
  </svg>`
120
96
  };
121
97
 
122
- return builtInIcons[iconName];
98
+ Object.keys(builtInIcons).forEach(name => {
99
+ this.icons[name] = builtInIcons[name];
100
+ this.cache.set(name, builtInIcons[name]);
101
+ });
102
+
103
+ console.log('📦 Загружены встроенные SVG иконки topbar');
123
104
  }
124
105
 
125
- loadBuiltInIcons() {
126
- // Загружаем встроенные иконки как основной источник
127
- const iconNames = ['grid-line', 'grid-dot', 'grid-cross', 'grid-off', 'paint'];
128
-
129
- for (const iconName of iconNames) {
130
- const builtInIcon = this.getBuiltInIcon(iconName);
131
- if (builtInIcon) {
132
- this.icons.set(iconName, builtInIcon);
133
- }
106
+ /**
107
+ * Загружает SVG иконку по имени
108
+ * @param {string} iconName - имя иконки без расширения
109
+ * @returns {Promise<string>} SVG содержимое
110
+ */
111
+ async loadIcon(iconName) {
112
+ if (this.cache.has(iconName)) {
113
+ console.log(`📦 Загружаем иконку ${iconName} из кэша`);
114
+ return this.cache.get(iconName);
134
115
  }
135
-
136
- console.log(`📦 Загружено ${this.icons.size} встроенных иконок верхней панели`);
137
- }
138
116
 
139
- getIcon(name) {
140
- return this.icons.get(name);
117
+ // Если иконка уже загружена статически
118
+ if (this.icons[iconName]) {
119
+ console.log(`📦 Загружаем иконку ${iconName} из статического кэша`);
120
+ return this.icons[iconName];
121
+ }
122
+
123
+ // Возвращаем fallback
124
+ console.warn(`⚠️ Иконка ${iconName} не найдена, используем fallback`);
125
+ return this.getFallbackIcon(iconName);
141
126
  }
142
127
 
143
128
  /**
144
- * Загружает все иконки и возвращает их как объект
129
+ * Загружает все иконки для topbar
130
+ * @returns {Promise<Object>} объект с иконками
145
131
  */
146
132
  async loadAllIcons() {
147
- const result = {};
148
- this.icons.forEach((content, name) => {
149
- result[name] = content;
150
- });
151
- return result;
133
+ // Если иконки еще не инициализированы
134
+ if (Object.keys(this.icons).length === 0) {
135
+ await this.init();
136
+ }
137
+
138
+ return this.icons;
152
139
  }
153
140
 
154
- reloadIcon(name) {
155
- // Перезагружаем конкретную иконку
156
- this.init();
141
+ /**
142
+ * Возвращает fallback иконку если загрузка не удалась
143
+ * @param {string} iconName - имя иконки
144
+ * @returns {string} fallback SVG
145
+ */
146
+ getFallbackIcon(iconName) {
147
+ // Простые fallback иконки в виде геометрических фигур
148
+ const fallbacks = {
149
+ 'grid-line': '<svg width="18" height="18" viewBox="0 0 18 18"><path d="M2 2H16V4H2V2Z" fill="currentColor"/><path d="M2 7H16V9H2V7Z" fill="currentColor"/><path d="M2 12H16V14H2V12Z" fill="currentColor"/><path d="M2 2V16H4V2H2Z" fill="currentColor"/><path d="M7 2V16H9V2H7Z" fill="currentColor"/><path d="M12 2V16H14V2H12Z" fill="currentColor"/></svg>',
150
+ 'grid-dot': '<svg width="18" height="18" viewBox="0 0 18 18"><circle cx="4" cy="4" r="1.5" fill="currentColor"/><circle cx="9" cy="4" r="1.5" fill="currentColor"/><circle cx="14" cy="4" r="1.5" fill="currentColor"/><circle cx="4" cy="9" r="1.5" fill="currentColor"/><circle cx="9" cy="9" r="1.5" fill="currentColor"/><circle cx="14" cy="9" r="1.5" fill="currentColor"/><circle cx="4" cy="14" r="1.5" fill="currentColor"/><circle cx="9" cy="14" r="1.5" fill="currentColor"/><circle cx="14" cy="14" r="1.5" fill="currentColor"/></svg>',
151
+ 'grid-cross': '<svg width="18" height="18" viewBox="0 0 18 18"><path d="M3 3L6 6M6 3L3 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M9 3L12 6M12 3L9 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M3 9L6 12M6 9L3 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M9 9L12 12M12 9L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
152
+ 'grid-off': '<svg width="18" height="18" viewBox="0 0 18 18"><path d="M2 2H16V4H2V2Z" fill="currentColor" opacity="0.3"/><path d="M2 7H16V9H2V7Z" fill="currentColor" opacity="0.3"/><path d="M2 12H16V14H2V12Z" fill="currentColor" opacity="0.3"/><path d="M2 2V16H4V2H2Z" fill="currentColor" opacity="0.3"/><path d="M7 2V16H9V2H7Z" fill="currentColor" opacity="0.3"/><path d="M12 2V16H14V2H12Z" fill="currentColor" opacity="0.3"/><path d="M1 17L17 1" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
153
+ 'paint': '<svg width="18" height="18" viewBox="0 0 18 18"><path d="M4 3H10L13 6V13A2 2 0 0 1 11 15H6A2 2 0 0 1 4 13V3Z" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M10 3V6H13" stroke="currentColor" stroke-width="1.5"/><path d="M14 10S15.5 11.5 15.5 13A1.5 1.5 0 0 1 13 13C13 11.5 14 10 14 10Z" fill="currentColor" stroke="currentColor" stroke-width="0.5"/></svg>'
154
+ };
155
+
156
+ return fallbacks[iconName] || fallbacks['grid-line'];
157
157
  }
158
158
 
159
+ /**
160
+ * Очищает кэш иконок
161
+ */
159
162
  clearCache() {
160
- this.icons.clear();
163
+ this.cache.clear();
161
164
  }
165
+
166
+ /**
167
+ * Принудительно перезагружает иконку (игнорируя кэш)
168
+ * @param {string} iconName - имя иконки без расширения
169
+ * @returns {Promise<string>} SVG содержимое
170
+ */
171
+ async reloadIcon(iconName) {
172
+ // Удаляем из кэша
173
+ console.log(`🗑️ Очищаем кэш для иконки ${iconName}`);
174
+ this.cache.delete(iconName);
175
+
176
+ try {
177
+ // Пробуем переимпортировать иконку
178
+ const iconModule = await import(`../assets/icons/${iconName}.svg?raw`);
179
+ if (iconModule && iconModule.default) {
180
+ const svgContent = iconModule.default;
181
+ console.log(`✅ Иконка ${iconName} перезагружена успешно`);
182
+ this.icons[iconName] = svgContent;
183
+ this.cache.set(iconName, svgContent);
184
+ return svgContent;
185
+ } else {
186
+ throw new Error(`Failed to reload icon: ${iconName}`);
187
+ }
188
+ } catch (error) {
189
+ console.error(`❌ Ошибка перезагрузки иконки ${iconName}:`, error);
190
+ return this.getFallbackIcon(iconName);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Получает иконку по имени (синхронный метод для совместимости)
196
+ */
197
+ getIcon(name) {
198
+ return this.icons[name] || this.getFallbackIcon(name);
199
+ }
200
+ }
201
+
202
+ // Создаем глобальный экземпляр
203
+ export const topbarIconLoader = new TopbarIconLoader();
204
+
205
+ // Добавляем в глобальную область для отладки
206
+ if (typeof window !== 'undefined') {
207
+ window.topbarIconLoader = topbarIconLoader;
162
208
  }
@@ -1,39 +0,0 @@
1
- # SVG Иконки для Верхней Панели
2
-
3
- Эта папка содержит SVG иконки для кнопок верхней панели MoodBoard.
4
-
5
- ## Иконки
6
-
7
- ### Сетка
8
- - **`grid-line.svg`** - Сетка с линиями
9
- - **`grid-dot.svg`** - Сетка с точками
10
- - **`grid-cross.svg`** - Сетка с крестиками
11
- - **`grid-off.svg`** - Сетка выключена (с перечеркиванием)
12
-
13
- ### Инструменты
14
- - **`paint.svg`** - Палитра фона
15
-
16
- ## Технические детали
17
-
18
- - **Размер**: 18x18 пикселей
19
- - **ViewBox**: 0 0 18 18
20
- - **Цвет**: Использует `currentColor` для наследования цвета от родительского элемента
21
- - **Формат**: SVG с оптимизированными путями
22
-
23
- ## Использование
24
-
25
- Иконки загружаются через `TopbarIconLoader` и добавляются в DOM как SVG символы с ID вида `icon-{имя}`.
26
-
27
- ```html
28
- <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
29
- <use href="#icon-grid-line"/>
30
- </svg>
31
- ```
32
-
33
- ## Добавление новых иконок
34
-
35
- 1. Создайте SVG файл в этой папке
36
- 2. Убедитесь, что используется `currentColor` для цвета
37
- 3. Добавьте иконку в `TopbarIconLoader.loadBuiltInIcons()` как fallback
38
- 4. Обновите соответствующий код в `Topbar.js`
39
-