@widgetic/editor 4.0.2 → 4.0.3
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/dist/components/MockWidget.svelte +1 -1
- package/dist/components/WidgetPreview.svelte +34 -50
- package/dist/components/editors/EmbedEditor.svelte +1 -1
- package/dist/components/editors/PropsEditor.svelte +173 -148
- package/dist/components/ic/BrowserInputController.svelte +14 -14
- package/dist/components/ic/CheckboxInputController.svelte +1 -1
- package/dist/components/ic/ColorPickerInputController.svelte +37 -37
- package/dist/components/ic/DatePickerInputController.svelte +6 -6
- package/dist/components/ic/DropdownInputController.svelte +1 -1
- package/dist/components/ic/FontInputController.svelte +136 -63
- package/dist/components/ic/FontInputController.svelte.d.ts +3 -1
- package/dist/components/ic/NumberInputController.svelte +37 -37
- package/dist/components/ic/RadioGroupInputController.svelte +1 -1
- package/dist/components/ic/SliderRangeInputController.svelte +1 -1
- package/dist/components/ic/SwitchInputController.svelte +1 -1
- package/dist/components/ic/TextAreaInputController.svelte +23 -23
- package/dist/components/ic/TextAreaPreviewInputController.svelte +2 -2
- package/dist/components/ic/VectorInputController.svelte +34 -34
- package/dist/components/ic/shared/CategoryTabs.svelte +1 -0
- package/dist/components/ic/shared/RecentItemsSection.svelte +21 -6
- package/dist/components/ic/shared/RecentItemsSection.svelte.d.ts +1 -0
- package/dist/stores/userSession.d.ts +1 -1
- package/dist/stores/userSession.js +17 -2
- package/dist/utils/FontManager.d.ts +1 -1
- package/dist/utils/FontManager.js +75 -102
- package/dist/utils/VectorManager.d.ts +3 -1
- package/dist/utils/VectorManager.js +30 -70
- package/dist/utils/colorTransparency.js +3 -3
- package/dist/utils/fontUtils.js +1 -1
- package/dist/utils/passiveEvents.d.ts +5 -0
- package/dist/utils/passiveEvents.js +9 -18
- package/dist/utils/recentColors.js +15 -15
- package/dist/utils/vectorUtils.js +1 -1
- package/package.json +1 -1
|
@@ -8,43 +8,68 @@ const fontWeightOrder = {
|
|
|
8
8
|
ExtraLight: 2,
|
|
9
9
|
Light: 3,
|
|
10
10
|
Regular: 4,
|
|
11
|
+
Italic: 4.5,
|
|
11
12
|
Medium: 5,
|
|
13
|
+
'Medium Italic': 5.5,
|
|
12
14
|
SemiBold: 6,
|
|
15
|
+
'SemiBold Italic': 6.5,
|
|
13
16
|
Bold: 7,
|
|
17
|
+
'Bold Italic': 7.5,
|
|
14
18
|
ExtraBold: 8,
|
|
19
|
+
'ExtraBold Italic': 8.5,
|
|
15
20
|
Black: 9,
|
|
21
|
+
'Black Italic': 9.5,
|
|
22
|
+
'Light Italic': 3.5,
|
|
23
|
+
'Thin Italic': 1.5,
|
|
24
|
+
'ExtraLight Italic': 2.5,
|
|
16
25
|
};
|
|
17
|
-
|
|
26
|
+
function googleVariantIdToWeightName(variant) {
|
|
27
|
+
const italic = /italic/i.test(variant);
|
|
28
|
+
const base = variant.replace(/italic/ig, '').toLowerCase() || 'regular';
|
|
29
|
+
let name;
|
|
30
|
+
switch (base) {
|
|
31
|
+
case '100':
|
|
32
|
+
name = 'Thin';
|
|
33
|
+
break;
|
|
34
|
+
case '200':
|
|
35
|
+
name = 'ExtraLight';
|
|
36
|
+
break;
|
|
37
|
+
case '300':
|
|
38
|
+
name = 'Light';
|
|
39
|
+
break;
|
|
40
|
+
case '400':
|
|
41
|
+
case 'regular':
|
|
42
|
+
case '':
|
|
43
|
+
name = 'Regular';
|
|
44
|
+
break;
|
|
45
|
+
case '500':
|
|
46
|
+
name = 'Medium';
|
|
47
|
+
break;
|
|
48
|
+
case '600':
|
|
49
|
+
name = 'SemiBold';
|
|
50
|
+
break;
|
|
51
|
+
case '700':
|
|
52
|
+
case 'bold':
|
|
53
|
+
name = 'Bold';
|
|
54
|
+
break;
|
|
55
|
+
case '800':
|
|
56
|
+
name = 'ExtraBold';
|
|
57
|
+
break;
|
|
58
|
+
case '900':
|
|
59
|
+
name = 'Black';
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
name = base;
|
|
63
|
+
}
|
|
64
|
+
if (!italic)
|
|
65
|
+
return name;
|
|
66
|
+
return name === 'Regular' ? 'Italic' : `${name} Italic`;
|
|
67
|
+
}
|
|
68
|
+
/** Maps Google Fonts API variant ids to display weight labels (includes italic faces). */
|
|
18
69
|
export function mapGoogleVariantIdsToWeightNames(variants) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
switch (v) {
|
|
23
|
-
case '100':
|
|
24
|
-
return 'Thin';
|
|
25
|
-
case '200':
|
|
26
|
-
return 'ExtraLight';
|
|
27
|
-
case '300':
|
|
28
|
-
return 'Light';
|
|
29
|
-
case '400':
|
|
30
|
-
case 'regular':
|
|
31
|
-
return 'Regular';
|
|
32
|
-
case '500':
|
|
33
|
-
return 'Medium';
|
|
34
|
-
case '600':
|
|
35
|
-
return 'SemiBold';
|
|
36
|
-
case '700':
|
|
37
|
-
case 'bold':
|
|
38
|
-
return 'Bold';
|
|
39
|
-
case '800':
|
|
40
|
-
return 'ExtraBold';
|
|
41
|
-
case '900':
|
|
42
|
-
return 'Black';
|
|
43
|
-
default:
|
|
44
|
-
return v;
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
.sort((a, b) => (fontWeightOrder[a] || 99) - (fontWeightOrder[b] || 99));
|
|
70
|
+
const names = variants.map(googleVariantIdToWeightName);
|
|
71
|
+
const unique = [...new Set(names)];
|
|
72
|
+
return unique.sort((a, b) => (fontWeightOrder[a] || 99) - (fontWeightOrder[b] || 99));
|
|
48
73
|
}
|
|
49
74
|
class FontManager {
|
|
50
75
|
// Debug configuration
|
|
@@ -122,7 +147,7 @@ class FontManager {
|
|
|
122
147
|
family,
|
|
123
148
|
category,
|
|
124
149
|
isCustom: false,
|
|
125
|
-
variants: ['regular', '500', '600', '700'],
|
|
150
|
+
variants: ['regular', 'italic', '500', '500italic', '600', '600italic', '700', '700italic'],
|
|
126
151
|
}));
|
|
127
152
|
return [
|
|
128
153
|
...pack(sans, 'Sans Serif'),
|
|
@@ -147,7 +172,7 @@ class FontManager {
|
|
|
147
172
|
FontManager.forbiddenApiKeyWarned = true;
|
|
148
173
|
console.warn('[FontManager] Google Fonts API returned 403 Forbidden. Fix in Google Cloud Console: ' +
|
|
149
174
|
'(1) Enable "Web Fonts Developer API" on the project, ' +
|
|
150
|
-
'(2) API key → Application restrictions → HTTP referrers: http://localhost:
|
|
175
|
+
'(2) API key → Application restrictions → HTTP referrers: http://localhost:5173/*, http://localhost:5174/*, http://localhost:5180/*, https://*.widgetic.com/*, ' +
|
|
151
176
|
'(3) use a key created for Web Fonts (not Gemini/other APIs). Font picker falls back to cached/custom fonts.');
|
|
152
177
|
}
|
|
153
178
|
warnBadRequestApiKey() {
|
|
@@ -155,7 +180,7 @@ class FontManager {
|
|
|
155
180
|
return;
|
|
156
181
|
FontManager.badRequestApiKeyWarned = true;
|
|
157
182
|
console.warn('[FontManager] Google Fonts API returned 400 Bad Request. Usually: invalid API key, Web Fonts Developer API not enabled, or wrong key type. ' +
|
|
158
|
-
'Use
|
|
183
|
+
'Use a Web Fonts Developer API key (not Gemini). Set PUBLIC_GOOGLE_FONTS_API_KEY and VITE_GOOGLE_FONTS_API_KEY in Frontend/site/.env and widget-creator/.env, restart Vite. ' +
|
|
159
184
|
'Font picker falls back to cached/custom fonts.');
|
|
160
185
|
}
|
|
161
186
|
/**
|
|
@@ -236,7 +261,7 @@ class FontManager {
|
|
|
236
261
|
*/
|
|
237
262
|
async initialize() {
|
|
238
263
|
if (FontManager.isInitialized) {
|
|
239
|
-
console.log('✅ [FontManager] Already initialized');
|
|
264
|
+
// console.log('✅ [FontManager] Already initialized');
|
|
240
265
|
return;
|
|
241
266
|
}
|
|
242
267
|
try {
|
|
@@ -271,74 +296,22 @@ class FontManager {
|
|
|
271
296
|
: await this.fetchGoogleFontsCatalog();
|
|
272
297
|
if (catalog?.length) {
|
|
273
298
|
this.catalog = { stage: 'complete', fonts: catalog };
|
|
274
|
-
//
|
|
299
|
+
// Index initial fonts for each category without blocking startup
|
|
275
300
|
const categories = ['Serif', 'Sans Serif', 'Script', 'Other'];
|
|
276
|
-
|
|
277
|
-
await Promise.all(categories.map(async (category) => {
|
|
301
|
+
categories.forEach(category => {
|
|
278
302
|
const categoryFonts = this.catalogFonts
|
|
279
303
|
.filter(font => fontCategories.normalize(font.category) === category)
|
|
280
304
|
.slice(0, FontManager.initialFontNumber);
|
|
281
305
|
this.categoryFonts.set(category, categoryFonts);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
try {
|
|
285
|
-
await this.insertFontStylesheet(font.family);
|
|
286
|
-
await this.loadFont(font.family, ['400', '500', '600', '700']);
|
|
287
|
-
}
|
|
288
|
-
catch (error) {
|
|
289
|
-
console.warn(`⚠️ [FontManager] Failed to preload font: ${font.family}`, error);
|
|
290
|
-
}
|
|
291
|
-
}));
|
|
292
|
-
// console.log(`📚 [FontManager] Preloaded fonts for ${category}:`, {
|
|
293
|
-
// total: categoryFonts.length,
|
|
294
|
-
// sample: categoryFonts.slice(0, 3).map(f => f.family)
|
|
295
|
-
// });
|
|
296
|
-
}));
|
|
297
|
-
// Save filtered list to localStorage cache
|
|
306
|
+
});
|
|
307
|
+
// Save filtered list to cache
|
|
298
308
|
this.saveFontListToCache(this.catalogFonts);
|
|
299
|
-
// console.log('📚 [FontManager] Complete font list cached:', {
|
|
300
|
-
// total: this.cachedFontList.length,
|
|
301
|
-
// categoriesPreloaded: Array.from(this.categoryFonts.keys())
|
|
302
|
-
// });
|
|
303
309
|
}
|
|
304
310
|
}
|
|
305
311
|
catch (error) {
|
|
306
312
|
// console.error('❌ [FontManager] Error caching complete font list:', error);
|
|
307
313
|
}
|
|
308
|
-
//
|
|
309
|
-
const initialFonts = [
|
|
310
|
-
'Roboto', 'Open Sans', 'Montserrat', 'Poppins',
|
|
311
|
-
'Lato', 'Inter'
|
|
312
|
-
].filter(font => !shouldSkipFont(font));
|
|
313
|
-
// Add popular fonts from the initial list
|
|
314
|
-
const popularFonts = initialFontList
|
|
315
|
-
.slice(0, FontManager.initialFontNumber)
|
|
316
|
-
.map(font => font.family)
|
|
317
|
-
.filter(family => !initialFonts.includes(family));
|
|
318
|
-
// Combine all fonts to preload: initial fonts + recent fonts + popular fonts
|
|
319
|
-
const fontsToLoad = [...new Set([
|
|
320
|
-
...initialFonts,
|
|
321
|
-
...recentFonts.map(font => font.family),
|
|
322
|
-
...popularFonts
|
|
323
|
-
])].filter(font => !this.loadedFonts.has(font));
|
|
324
|
-
if (fontsToLoad.length > 0) {
|
|
325
|
-
// console.log('🔄 [FontManager] Preloading fonts:', fontsToLoad);
|
|
326
|
-
// Load all fonts in parallel with all weights
|
|
327
|
-
const loadPromises = fontsToLoad.map(async (family) => {
|
|
328
|
-
try {
|
|
329
|
-
await this.insertFontStylesheet(family);
|
|
330
|
-
await this.loadFont(family, ['400', '500', '600', '700']);
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
console.warn(`⚠️ [FontManager] Failed to load font: ${family}`, error);
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
await Promise.all(loadPromises);
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
console.log('✨ [FontManager] All initial fonts already cached');
|
|
340
|
-
}
|
|
341
|
-
// Only set initialized after everything is complete
|
|
314
|
+
// Only set initialized after catalog/custom setup is complete
|
|
342
315
|
FontManager.isInitialized = true;
|
|
343
316
|
// console.log('✅ [FontManager] Initialization complete. Font status:', {
|
|
344
317
|
// totalLoaded: this.loadedFonts.size,
|
|
@@ -703,7 +676,7 @@ class FontManager {
|
|
|
703
676
|
return null;
|
|
704
677
|
// Check if cache is expired
|
|
705
678
|
if (Date.now() - cache.timestamp > FontManager.CACHE_DURATION) {
|
|
706
|
-
console.log('⚠️ [FontManager] Cache expired, removing');
|
|
679
|
+
// console.log('⚠️ [FontManager] Cache expired, removing');
|
|
707
680
|
void deleteKvValue(FontManager.CACHE_KEY);
|
|
708
681
|
return null;
|
|
709
682
|
}
|
|
@@ -766,13 +739,13 @@ class FontManager {
|
|
|
766
739
|
}
|
|
767
740
|
// Return immediately if preload is already complete
|
|
768
741
|
if (FontManager.initialPreloadComplete) {
|
|
769
|
-
console.log('✅ [FontManager] Initial fonts already preloaded');
|
|
742
|
+
// console.log('✅ [FontManager] Initial fonts already preloaded');
|
|
770
743
|
return;
|
|
771
744
|
}
|
|
772
745
|
// Create new preload promise
|
|
773
746
|
FontManager.preloadPromise = (async () => {
|
|
774
747
|
try {
|
|
775
|
-
console.log('🚀 [FontManager] Preloading initial fonts...');
|
|
748
|
+
// console.log('🚀 [FontManager] Preloading initial fonts...');
|
|
776
749
|
const initialFonts = await this.getInitialFontList();
|
|
777
750
|
const loadPromises = initialFonts.map(font => {
|
|
778
751
|
this.insertFontStylesheet(font.family);
|
|
@@ -780,7 +753,7 @@ class FontManager {
|
|
|
780
753
|
});
|
|
781
754
|
await Promise.all(loadPromises);
|
|
782
755
|
FontManager.initialPreloadComplete = true;
|
|
783
|
-
console.log('✅ [FontManager] Initial fonts preloaded');
|
|
756
|
+
// console.log('✅ [FontManager] Initial fonts preloaded');
|
|
784
757
|
}
|
|
785
758
|
catch (error) {
|
|
786
759
|
console.error('❌ [FontManager] Error preloading initial fonts:', error);
|
|
@@ -1169,12 +1142,12 @@ class FontManager {
|
|
|
1169
1142
|
? Array.from(this.customFonts.values())
|
|
1170
1143
|
: this.catalogFonts.filter(font => fontCategories.normalize(font.category) === category);
|
|
1171
1144
|
const remainingItems = categoryFonts.length - currentIndex;
|
|
1172
|
-
console.log('🔍 [FontManager] Checking remaining fonts:', {
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
});
|
|
1145
|
+
// console.log('🔍 [FontManager] Checking remaining fonts:', {
|
|
1146
|
+
// category,
|
|
1147
|
+
// currentIndex,
|
|
1148
|
+
// totalInCategory: categoryFonts.length,
|
|
1149
|
+
// remainingItems
|
|
1150
|
+
// });
|
|
1178
1151
|
// Only return true if we have more items in this category
|
|
1179
1152
|
return remainingItems > 0;
|
|
1180
1153
|
}
|
|
@@ -1223,7 +1196,7 @@ class FontManager {
|
|
|
1223
1196
|
fonts: this.catalog.fonts.filter(font => font.family !== family || font.category !== 'Mine'),
|
|
1224
1197
|
};
|
|
1225
1198
|
}
|
|
1226
|
-
console.log('✅ [FontManager] Custom font removed:', family);
|
|
1199
|
+
// console.log('✅ [FontManager] Custom font removed:', family);
|
|
1227
1200
|
}
|
|
1228
1201
|
}
|
|
1229
1202
|
catch (error) {
|
|
@@ -46,6 +46,8 @@ declare class VectorManager {
|
|
|
46
46
|
static isInitialized: boolean;
|
|
47
47
|
static initialVectorNumber: number;
|
|
48
48
|
private static initializationPromise;
|
|
49
|
+
private static svgsFetchPromise;
|
|
50
|
+
private static fetchSvgsJson;
|
|
49
51
|
private remainingTime;
|
|
50
52
|
private preInitializedObservers;
|
|
51
53
|
static readonly BATCH_SIZE = 100;
|
|
@@ -86,7 +88,7 @@ declare class VectorManager {
|
|
|
86
88
|
*/
|
|
87
89
|
getInitialVectorList(): Promise<VectorData[]>;
|
|
88
90
|
/**
|
|
89
|
-
* Saves vector list to localStorage
|
|
91
|
+
* Saves vector list to cache (avoids writing 1.2MB JSON to localStorage)
|
|
90
92
|
*/
|
|
91
93
|
private saveVectorListToCache;
|
|
92
94
|
/**
|
|
@@ -33,6 +33,22 @@ class VectorManager {
|
|
|
33
33
|
static initialVectorNumber = 8; // 8 - how many vectors to load initially
|
|
34
34
|
// Add a static property to track initialization state
|
|
35
35
|
static initializationPromise = null;
|
|
36
|
+
static svgsFetchPromise = null;
|
|
37
|
+
static async fetchSvgsJson() {
|
|
38
|
+
if (!VectorManager.svgsFetchPromise) {
|
|
39
|
+
VectorManager.svgsFetchPromise = fetch('/svgs.json')
|
|
40
|
+
.then(response => {
|
|
41
|
+
if (!response.ok)
|
|
42
|
+
throw new Error('Failed to fetch vectors');
|
|
43
|
+
return response.json();
|
|
44
|
+
})
|
|
45
|
+
.catch(err => {
|
|
46
|
+
VectorManager.svgsFetchPromise = null;
|
|
47
|
+
throw err;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return VectorManager.svgsFetchPromise;
|
|
51
|
+
}
|
|
36
52
|
// Add this property
|
|
37
53
|
remainingTime = 0;
|
|
38
54
|
// Add a Map to store pre-initialized observers
|
|
@@ -97,54 +113,24 @@ class VectorManager {
|
|
|
97
113
|
category: vectorCategories.normalize(vector.category),
|
|
98
114
|
url: vector.url
|
|
99
115
|
}));
|
|
100
|
-
// Get initial vector list and cache it
|
|
116
|
+
// Get initial vector list and cache it (deduplicated fetch)
|
|
101
117
|
const initialVectorList = await this.getInitialVectorList();
|
|
102
118
|
// console.log('📋 [VectorManager] Initial vector list loaded:', initialVectorList.length);
|
|
103
|
-
//
|
|
119
|
+
// Setup category indexing without eager vector preloading
|
|
104
120
|
try {
|
|
105
|
-
// Load vectors from svgs.json instead of API
|
|
106
|
-
const response = await fetch('/svgs.json');
|
|
107
|
-
if (!response.ok)
|
|
108
|
-
throw new Error('Failed to fetch vectors');
|
|
109
|
-
const data = await response.json();
|
|
110
|
-
// Convert to VectorData format and cache
|
|
111
|
-
this.cachedVectorList = data.svgGroups.flatMap((group) => group.items.map((item) => ({
|
|
112
|
-
name: item.name,
|
|
113
|
-
category: vectorCategories.normalize(group.category),
|
|
114
|
-
url: item.url
|
|
115
|
-
})));
|
|
116
|
-
// Preload initial vectors for each category
|
|
117
121
|
const categories = ['Icons', 'Emojis', 'Clipart', 'Mine'];
|
|
118
|
-
|
|
119
|
-
await Promise.all(categories.map(async (category) => {
|
|
122
|
+
categories.forEach(category => {
|
|
120
123
|
const categoryVectors = this.cachedVectorList
|
|
121
124
|
.filter(vector => vectorCategories.normalize(vector.category) === category)
|
|
122
125
|
.slice(0, VectorManager.initialVectorNumber);
|
|
123
126
|
this.categoryVectors.set(category, categoryVectors);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await this.loadVector(vector.name);
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
console.warn(`⚠️ [VectorManager] Failed to preload vector: ${vector.name}`, error);
|
|
131
|
-
}
|
|
132
|
-
}));
|
|
133
|
-
// console.log(`📚 [VectorManager] Preloaded vectors for ${category}:`, {
|
|
134
|
-
// total: categoryVectors.length,
|
|
135
|
-
// sample: categoryVectors.slice(0, 3).map(v => v.name)
|
|
136
|
-
// });
|
|
137
|
-
}));
|
|
138
|
-
// Save filtered list to localStorage cache
|
|
127
|
+
});
|
|
128
|
+
// Clean up legacy cache and mark loaded
|
|
139
129
|
this.saveVectorListToCache(this.cachedVectorList);
|
|
140
130
|
this.allVectorsLoaded = true;
|
|
141
|
-
// console.log('📚 [VectorManager] Complete vector list cached:', {
|
|
142
|
-
// total: this.cachedVectorList.length,
|
|
143
|
-
// categoriesPreloaded: Array.from(this.categoryVectors.keys())
|
|
144
|
-
// });
|
|
145
131
|
}
|
|
146
132
|
catch (error) {
|
|
147
|
-
console.error('❌ [VectorManager] Error
|
|
133
|
+
console.error('❌ [VectorManager] Error indexing vector list:', error);
|
|
148
134
|
}
|
|
149
135
|
// Only set initialized after everything is complete
|
|
150
136
|
VectorManager.isInitialized = true;
|
|
@@ -292,11 +278,8 @@ class VectorManager {
|
|
|
292
278
|
}));
|
|
293
279
|
// Add custom vectors from custom-svgs.json
|
|
294
280
|
const customVectors = await this.loadCustomVectors();
|
|
295
|
-
// Load vectors from svgs.json
|
|
296
|
-
const
|
|
297
|
-
if (!response.ok)
|
|
298
|
-
throw new Error('Failed to fetch vectors');
|
|
299
|
-
const data = await response.json();
|
|
281
|
+
// Load vectors from svgs.json using deduplicated fetch promise
|
|
282
|
+
const data = await VectorManager.fetchSvgsJson();
|
|
300
283
|
// Process and combine vectors
|
|
301
284
|
const standardVectors = data.svgGroups.flatMap((group) => group.items.map((item) => ({
|
|
302
285
|
name: item.name,
|
|
@@ -320,22 +303,15 @@ class VectorManager {
|
|
|
320
303
|
}
|
|
321
304
|
}
|
|
322
305
|
/**
|
|
323
|
-
* Saves vector list to localStorage
|
|
306
|
+
* Saves vector list to cache (avoids writing 1.2MB JSON to localStorage)
|
|
324
307
|
*/
|
|
325
308
|
saveVectorListToCache(vectors) {
|
|
326
309
|
try {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
vectors: vectors
|
|
330
|
-
};
|
|
331
|
-
localStorage.setItem(VectorManager.CACHE_KEY, JSON.stringify(cacheData));
|
|
332
|
-
// console.log('💾 [VectorManager] Vector list cached:', {
|
|
333
|
-
// vectors: vectors.length,
|
|
334
|
-
// expires: new Date(cacheData.timestamp + VectorManager.CACHE_DURATION)
|
|
335
|
-
// });
|
|
310
|
+
// Remove legacy large JSON from localStorage if present to free storage quota
|
|
311
|
+
localStorage.removeItem(VectorManager.CACHE_KEY);
|
|
336
312
|
}
|
|
337
313
|
catch (error) {
|
|
338
|
-
|
|
314
|
+
// Ignore storage errors
|
|
339
315
|
}
|
|
340
316
|
}
|
|
341
317
|
/**
|
|
@@ -672,7 +648,7 @@ class VectorManager {
|
|
|
672
648
|
return this.observers.get(key) || null;
|
|
673
649
|
}
|
|
674
650
|
// Create new observer
|
|
675
|
-
console.log('🔧 [VectorManager] Creating new observer for container:', key);
|
|
651
|
+
// console.log('🔧 [VectorManager] Creating new observer for container:', key);
|
|
676
652
|
const observer = new IntersectionObserver((entries) => {
|
|
677
653
|
entries.forEach(entry => {
|
|
678
654
|
const vectorName = entry.target.getAttribute('data-vector');
|
|
@@ -732,23 +708,7 @@ class VectorManager {
|
|
|
732
708
|
* Returns null if cache is invalid or expired
|
|
733
709
|
*/
|
|
734
710
|
getVectorListFromCache() {
|
|
735
|
-
|
|
736
|
-
const cached = localStorage.getItem(VectorManager.CACHE_KEY);
|
|
737
|
-
if (!cached)
|
|
738
|
-
return null;
|
|
739
|
-
const cache = JSON.parse(cached);
|
|
740
|
-
const now = Date.now();
|
|
741
|
-
// Check if cache has expired
|
|
742
|
-
if (now - cache.timestamp > VectorManager.CACHE_DURATION) {
|
|
743
|
-
console.log('📅 [VectorManager] Cache expired, will refresh');
|
|
744
|
-
return null;
|
|
745
|
-
}
|
|
746
|
-
return cache.vectors;
|
|
747
|
-
}
|
|
748
|
-
catch (error) {
|
|
749
|
-
console.error('❌ [VectorManager] Error reading vector cache:', error);
|
|
750
|
-
return null;
|
|
751
|
-
}
|
|
711
|
+
return null;
|
|
752
712
|
}
|
|
753
713
|
}
|
|
754
714
|
export default VectorManager;
|
|
@@ -12,7 +12,7 @@ export class ColorTransparencyHandler {
|
|
|
12
12
|
* Converts hex color to RGBA while preserving opacity
|
|
13
13
|
*/
|
|
14
14
|
hexToRgba(hex) {
|
|
15
|
-
console.log('Converting hex to rgba:', hex, 'Current opacity:', this.persistentOpacity);
|
|
15
|
+
// console.log('Converting hex to rgba:', hex, 'Current opacity:', this.persistentOpacity);
|
|
16
16
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i.exec(hex);
|
|
17
17
|
if (result) {
|
|
18
18
|
return {
|
|
@@ -57,7 +57,7 @@ export class ColorTransparencyHandler {
|
|
|
57
57
|
finally {
|
|
58
58
|
this.isInternalUpdate = false;
|
|
59
59
|
}
|
|
60
|
-
console.log('Updated opacity:', newOpacity);
|
|
60
|
+
// console.log('Updated opacity:', newOpacity);
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Updates opacity from input value
|
|
@@ -75,7 +75,7 @@ export class ColorTransparencyHandler {
|
|
|
75
75
|
finally {
|
|
76
76
|
this.isInternalUpdate = false;
|
|
77
77
|
}
|
|
78
|
-
console.log('Updated opacity from input:', value);
|
|
78
|
+
// console.log('Updated opacity from input:', value);
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
81
|
* Gets the current opacity percentage
|
package/dist/utils/fontUtils.js
CHANGED
|
@@ -15,7 +15,7 @@ export const fontCategories = {
|
|
|
15
15
|
normalize(category) {
|
|
16
16
|
// Handle null or undefined category
|
|
17
17
|
if (!category) {
|
|
18
|
-
console.log('⚠️ [FontUtils] Null category, returning Other');
|
|
18
|
+
// console.log('⚠️ [FontUtils] Null category, returning Other');
|
|
19
19
|
return 'Other';
|
|
20
20
|
}
|
|
21
21
|
// Convert to lowercase and trim for consistent matching
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passive event listener helper.
|
|
3
|
+
* Apply specifically to scroll-listening elements that do not call preventDefault().
|
|
4
|
+
*/
|
|
5
|
+
export declare function addPassiveEventListener<K extends keyof WindowEventMap>(target: EventTarget, type: K, listener: (this: EventTarget, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): () => void;
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (typeof options === 'object') {
|
|
11
|
-
newOptions = { ...options, passive: true };
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
newOptions = { passive: true };
|
|
15
|
-
}
|
|
16
|
-
return originalAddEventListener.call(this, type, listener, newOptions);
|
|
17
|
-
}
|
|
18
|
-
return originalAddEventListener.call(this, type, listener, options);
|
|
1
|
+
/**
|
|
2
|
+
* Passive event listener helper.
|
|
3
|
+
* Apply specifically to scroll-listening elements that do not call preventDefault().
|
|
4
|
+
*/
|
|
5
|
+
export function addPassiveEventListener(target, type, listener, options) {
|
|
6
|
+
const opts = typeof options === 'object' ? { ...options, passive: true } : { passive: true };
|
|
7
|
+
target.addEventListener(type, listener, opts);
|
|
8
|
+
return () => {
|
|
9
|
+
target.removeEventListener(type, listener, opts);
|
|
19
10
|
};
|
|
20
11
|
}
|
|
@@ -14,31 +14,31 @@ export const recentColorsUtil = {
|
|
|
14
14
|
addRecentColor(color, alpha) {
|
|
15
15
|
try {
|
|
16
16
|
const normalizedColor = color.toLowerCase();
|
|
17
|
-
console.log('Adding/updating recent color:', {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
17
|
+
// console.log('Adding/updating recent color:', {
|
|
18
|
+
// normalizedColor,
|
|
19
|
+
// alpha,
|
|
20
|
+
// originalColor: color
|
|
21
|
+
// });
|
|
22
22
|
let colors = this.getRecentColors();
|
|
23
23
|
// Normalize all colors for comparison
|
|
24
24
|
const existingIndex = colors.findIndex(c => {
|
|
25
25
|
const normalizedExisting = c.color.toLowerCase();
|
|
26
26
|
const alphaMatch = Math.abs(c.alpha - alpha) < 0.001;
|
|
27
|
-
console.log('Comparing:', {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
27
|
+
// console.log('Comparing:', {
|
|
28
|
+
// existing: normalizedExisting,
|
|
29
|
+
// new: normalizedColor,
|
|
30
|
+
// existingAlpha: c.alpha,
|
|
31
|
+
// newAlpha: alpha,
|
|
32
|
+
// alphaMatch,
|
|
33
|
+
// colorsMatch: normalizedExisting === normalizedColor
|
|
34
|
+
// });
|
|
35
35
|
return normalizedExisting === normalizedColor && alphaMatch;
|
|
36
36
|
});
|
|
37
|
-
console.log('Found existing color at index:', existingIndex);
|
|
37
|
+
// console.log('Found existing color at index:', existingIndex);
|
|
38
38
|
if (existingIndex !== -1) {
|
|
39
39
|
// Remove the existing color
|
|
40
40
|
const removed = colors.splice(existingIndex, 1)[0];
|
|
41
|
-
console.log('Removed existing color:', removed);
|
|
41
|
+
// console.log('Removed existing color:', removed);
|
|
42
42
|
}
|
|
43
43
|
// Add the new/updated color to the front
|
|
44
44
|
const newColor = {
|
|
@@ -10,7 +10,7 @@ export const vectorCategories = {
|
|
|
10
10
|
normalize(category) {
|
|
11
11
|
// Handle null or undefined category
|
|
12
12
|
if (!category) {
|
|
13
|
-
console.log('⚠️ [VectorUtils] Null category, returning Icons');
|
|
13
|
+
// console.log('⚠️ [VectorUtils] Null category, returning Icons');
|
|
14
14
|
return 'Icons';
|
|
15
15
|
}
|
|
16
16
|
// Convert to lowercase and trim for consistent matching
|