@widgetic/editor 4.0.1 → 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.
Files changed (39) hide show
  1. package/dist/components/MockWidget.svelte +1 -1
  2. package/dist/components/WidgetPreview.svelte +36 -52
  3. package/dist/components/editors/EmbedEditor.svelte +1 -1
  4. package/dist/components/editors/PropsEditor.svelte +309 -227
  5. package/dist/components/ic/BrowserInputController.svelte +26 -19
  6. package/dist/components/ic/CheckboxInputController.svelte +1 -1
  7. package/dist/components/ic/ColorPickerInputController.svelte +37 -37
  8. package/dist/components/ic/DatePickerInputController.svelte +6 -6
  9. package/dist/components/ic/DropdownInputController.svelte +1 -1
  10. package/dist/components/ic/FontInputController.svelte +225 -116
  11. package/dist/components/ic/FontInputController.svelte.d.ts +4 -2
  12. package/dist/components/ic/NumberInputController.svelte +37 -37
  13. package/dist/components/ic/RadioGroupInputController.svelte +1 -1
  14. package/dist/components/ic/SliderRangeInputController.svelte +1 -1
  15. package/dist/components/ic/SwitchInputController.svelte +1 -1
  16. package/dist/components/ic/TextAreaInputController.svelte +213 -85
  17. package/dist/components/ic/TextAreaInputController.svelte.d.ts +1 -0
  18. package/dist/components/ic/TextAreaPreviewInputController.svelte +81 -79
  19. package/dist/components/ic/VectorInputController.svelte +34 -34
  20. package/dist/components/ic/shared/CategoryTabs.svelte +1 -0
  21. package/dist/components/ic/shared/RecentItemsSection.svelte +21 -6
  22. package/dist/components/ic/shared/RecentItemsSection.svelte.d.ts +1 -0
  23. package/dist/config.d.ts +6 -0
  24. package/dist/config.js +19 -7
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +1 -0
  27. package/dist/stores/userSession.d.ts +1 -1
  28. package/dist/stores/userSession.js +17 -2
  29. package/dist/utils/FontManager.d.ts +3 -1
  30. package/dist/utils/FontManager.js +95 -103
  31. package/dist/utils/VectorManager.d.ts +3 -1
  32. package/dist/utils/VectorManager.js +30 -70
  33. package/dist/utils/colorTransparency.js +3 -3
  34. package/dist/utils/fontUtils.js +1 -1
  35. package/dist/utils/passiveEvents.d.ts +5 -0
  36. package/dist/utils/passiveEvents.js +9 -18
  37. package/dist/utils/recentColors.js +15 -15
  38. package/dist/utils/vectorUtils.js +1 -1
  39. package/package.json +1 -1
@@ -1,7 +1,22 @@
1
1
  import { writable } from 'svelte/store';
2
+ const isBrowser = typeof window !== 'undefined';
3
+ let initialJwt = null;
4
+ let initialUser = null;
5
+ if (isBrowser) {
6
+ try {
7
+ initialJwt = localStorage.getItem('jwt');
8
+ const userStr = localStorage.getItem('user');
9
+ if (userStr) {
10
+ initialUser = JSON.parse(userStr);
11
+ }
12
+ }
13
+ catch (error) {
14
+ console.error('Failed to read initial session from localStorage:', error);
15
+ }
16
+ }
2
17
  export const userSession = writable({
3
- user: null,
4
- jwt: null
18
+ user: initialUser,
19
+ jwt: initialJwt
5
20
  });
6
21
  export function setSession(user, jwt) {
7
22
  userSession.set({ user, jwt });
@@ -25,7 +25,7 @@ export interface FontData {
25
25
  /** Google Web Fonts API variant ids (e.g. "400", "700", "regular") */
26
26
  variants?: string[];
27
27
  }
28
- /** Maps Google Fonts API variant ids to display weight labels. */
28
+ /** Maps Google Fonts API variant ids to display weight labels (includes italic faces). */
29
29
  export declare function mapGoogleVariantIdsToWeightNames(variants: string[]): string[];
30
30
  declare class FontManager {
31
31
  private static readonly DEBUG_MODE;
@@ -70,6 +70,8 @@ declare class FontManager {
70
70
  private static forbiddenApiKeyWarned;
71
71
  private static badRequestApiKeyWarned;
72
72
  private catalogFetchPromise;
73
+ /** Popular Google families shown when the Web Fonts API key is missing or blocked. */
74
+ private static getFallbackCatalog;
73
75
  private hasGoogleFontsApiKey;
74
76
  private warnMissingApiKey;
75
77
  private warnForbiddenApiKey;
@@ -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
- /** Maps Google Fonts API variant ids to display weight labels. */
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
- return variants
20
- .filter((v) => !v.includes('italic'))
21
- .map((v) => {
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
@@ -112,6 +137,25 @@ class FontManager {
112
137
  static forbiddenApiKeyWarned = false;
113
138
  static badRequestApiKeyWarned = false;
114
139
  catalogFetchPromise = null;
140
+ /** Popular Google families shown when the Web Fonts API key is missing or blocked. */
141
+ static getFallbackCatalog() {
142
+ const sans = ['Inter', 'Roboto', 'Open Sans', 'Poppins', 'Lato', 'Montserrat', 'Nunito', 'Source Sans 3', 'Work Sans', 'DM Sans'];
143
+ const serif = ['Playfair Display', 'Merriweather', 'Libre Baskerville', 'Lora', 'Cormorant Garamond'];
144
+ const script = ['Dancing Script', 'Pacifico', 'Great Vibes'];
145
+ const other = ['Oswald', 'Raleway', 'Space Grotesk'];
146
+ const pack = (families, category) => families.map((family) => ({
147
+ family,
148
+ category,
149
+ isCustom: false,
150
+ variants: ['regular', 'italic', '500', '500italic', '600', '600italic', '700', '700italic'],
151
+ }));
152
+ return [
153
+ ...pack(sans, 'Sans Serif'),
154
+ ...pack(serif, 'Serif'),
155
+ ...pack(script, 'Script'),
156
+ ...pack(other, 'Other'),
157
+ ];
158
+ }
115
159
  hasGoogleFontsApiKey() {
116
160
  return Boolean(this.apiKey?.trim());
117
161
  }
@@ -128,7 +172,7 @@ class FontManager {
128
172
  FontManager.forbiddenApiKeyWarned = true;
129
173
  console.warn('[FontManager] Google Fonts API returned 403 Forbidden. Fix in Google Cloud Console: ' +
130
174
  '(1) Enable "Web Fonts Developer API" on the project, ' +
131
- '(2) API key → Application restrictions → HTTP referrers: http://localhost:5180/*, http://localhost:5174/*, http://127.0.0.1:5180/*, https://*.widgetic.com/*, ' +
175
+ '(2) API key → Application restrictions → HTTP referrers: http://localhost:5173/*, http://localhost:5174/*, http://localhost:5180/*, https://*.widgetic.com/*, ' +
132
176
  '(3) use a key created for Web Fonts (not Gemini/other APIs). Font picker falls back to cached/custom fonts.');
133
177
  }
134
178
  warnBadRequestApiKey() {
@@ -136,7 +180,7 @@ class FontManager {
136
180
  return;
137
181
  FontManager.badRequestApiKeyWarned = true;
138
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. ' +
139
- 'Use the "Widgetic-Fonts" key from Google Cloud (Web Fonts API only), set VITE_GOOGLE_FONTS_API_KEY in widget-creator/.env, restart dev server. ' +
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. ' +
140
184
  'Font picker falls back to cached/custom fonts.');
141
185
  }
142
186
  /**
@@ -217,7 +261,7 @@ class FontManager {
217
261
  */
218
262
  async initialize() {
219
263
  if (FontManager.isInitialized) {
220
- console.log('✅ [FontManager] Already initialized');
264
+ // console.log('✅ [FontManager] Already initialized');
221
265
  return;
222
266
  }
223
267
  try {
@@ -252,74 +296,22 @@ class FontManager {
252
296
  : await this.fetchGoogleFontsCatalog();
253
297
  if (catalog?.length) {
254
298
  this.catalog = { stage: 'complete', fonts: catalog };
255
- // Preload initial fonts for each category
299
+ // Index initial fonts for each category without blocking startup
256
300
  const categories = ['Serif', 'Sans Serif', 'Script', 'Other'];
257
- // Preload fonts for each category
258
- await Promise.all(categories.map(async (category) => {
301
+ categories.forEach(category => {
259
302
  const categoryFonts = this.catalogFonts
260
303
  .filter(font => fontCategories.normalize(font.category) === category)
261
304
  .slice(0, FontManager.initialFontNumber);
262
305
  this.categoryFonts.set(category, categoryFonts);
263
- // Preload the fonts by inserting their stylesheets
264
- await Promise.all(categoryFonts.map(async (font) => {
265
- try {
266
- await this.insertFontStylesheet(font.family);
267
- await this.loadFont(font.family, ['400', '500', '600', '700']);
268
- }
269
- catch (error) {
270
- console.warn(`⚠️ [FontManager] Failed to preload font: ${font.family}`, error);
271
- }
272
- }));
273
- // console.log(`📚 [FontManager] Preloaded fonts for ${category}:`, {
274
- // total: categoryFonts.length,
275
- // sample: categoryFonts.slice(0, 3).map(f => f.family)
276
- // });
277
- }));
278
- // Save filtered list to localStorage cache
306
+ });
307
+ // Save filtered list to cache
279
308
  this.saveFontListToCache(this.catalogFonts);
280
- // console.log('📚 [FontManager] Complete font list cached:', {
281
- // total: this.cachedFontList.length,
282
- // categoriesPreloaded: Array.from(this.categoryFonts.keys())
283
- // });
284
309
  }
285
310
  }
286
311
  catch (error) {
287
312
  // console.error('❌ [FontManager] Error caching complete font list:', error);
288
313
  }
289
- // Define initial fonts that must be loaded (excluding skipped fonts)
290
- const initialFonts = [
291
- 'Roboto', 'Open Sans', 'Montserrat', 'Poppins',
292
- 'Lato', 'Inter'
293
- ].filter(font => !shouldSkipFont(font));
294
- // Add popular fonts from the initial list
295
- const popularFonts = initialFontList
296
- .slice(0, FontManager.initialFontNumber)
297
- .map(font => font.family)
298
- .filter(family => !initialFonts.includes(family));
299
- // Combine all fonts to preload: initial fonts + recent fonts + popular fonts
300
- const fontsToLoad = [...new Set([
301
- ...initialFonts,
302
- ...recentFonts.map(font => font.family),
303
- ...popularFonts
304
- ])].filter(font => !this.loadedFonts.has(font));
305
- if (fontsToLoad.length > 0) {
306
- // console.log('🔄 [FontManager] Preloading fonts:', fontsToLoad);
307
- // Load all fonts in parallel with all weights
308
- const loadPromises = fontsToLoad.map(async (family) => {
309
- try {
310
- await this.insertFontStylesheet(family);
311
- await this.loadFont(family, ['400', '500', '600', '700']);
312
- }
313
- catch (error) {
314
- console.warn(`⚠️ [FontManager] Failed to load font: ${family}`, error);
315
- }
316
- });
317
- await Promise.all(loadPromises);
318
- }
319
- else {
320
- console.log('✨ [FontManager] All initial fonts already cached');
321
- }
322
- // Only set initialized after everything is complete
314
+ // Only set initialized after catalog/custom setup is complete
323
315
  FontManager.isInitialized = true;
324
316
  // console.log('✅ [FontManager] Initialization complete. Font status:', {
325
317
  // totalLoaded: this.loadedFonts.size,
@@ -621,7 +613,7 @@ class FontManager {
621
613
  // Add custom fonts from fonts.json
622
614
  const customFonts = await this.loadCustomFonts();
623
615
  const catalog = await this.fetchGoogleFontsCatalog();
624
- const googleFonts = catalog || [];
616
+ const googleFonts = (catalog && catalog.length > 0) ? catalog : FontManager.getFallbackCatalog();
625
617
  // Combine all fonts. A full Google catalog means the list is already
626
618
  // complete; otherwise keep the 'initial' stage so a later fetch can
627
619
  // still upgrade it.
@@ -638,7 +630,7 @@ class FontManager {
638
630
  }
639
631
  catch (error) {
640
632
  console.error('Error getting initial fonts:', error);
641
- return [];
633
+ return FontManager.getFallbackCatalog();
642
634
  }
643
635
  }
644
636
  /**
@@ -684,7 +676,7 @@ class FontManager {
684
676
  return null;
685
677
  // Check if cache is expired
686
678
  if (Date.now() - cache.timestamp > FontManager.CACHE_DURATION) {
687
- console.log('⚠️ [FontManager] Cache expired, removing');
679
+ // console.log('⚠️ [FontManager] Cache expired, removing');
688
680
  void deleteKvValue(FontManager.CACHE_KEY);
689
681
  return null;
690
682
  }
@@ -747,13 +739,13 @@ class FontManager {
747
739
  }
748
740
  // Return immediately if preload is already complete
749
741
  if (FontManager.initialPreloadComplete) {
750
- console.log('✅ [FontManager] Initial fonts already preloaded');
742
+ // console.log('✅ [FontManager] Initial fonts already preloaded');
751
743
  return;
752
744
  }
753
745
  // Create new preload promise
754
746
  FontManager.preloadPromise = (async () => {
755
747
  try {
756
- console.log('🚀 [FontManager] Preloading initial fonts...');
748
+ // console.log('🚀 [FontManager] Preloading initial fonts...');
757
749
  const initialFonts = await this.getInitialFontList();
758
750
  const loadPromises = initialFonts.map(font => {
759
751
  this.insertFontStylesheet(font.family);
@@ -761,7 +753,7 @@ class FontManager {
761
753
  });
762
754
  await Promise.all(loadPromises);
763
755
  FontManager.initialPreloadComplete = true;
764
- console.log('✅ [FontManager] Initial fonts preloaded');
756
+ // console.log('✅ [FontManager] Initial fonts preloaded');
765
757
  }
766
758
  catch (error) {
767
759
  console.error('❌ [FontManager] Error preloading initial fonts:', error);
@@ -1150,12 +1142,12 @@ class FontManager {
1150
1142
  ? Array.from(this.customFonts.values())
1151
1143
  : this.catalogFonts.filter(font => fontCategories.normalize(font.category) === category);
1152
1144
  const remainingItems = categoryFonts.length - currentIndex;
1153
- console.log('🔍 [FontManager] Checking remaining fonts:', {
1154
- category,
1155
- currentIndex,
1156
- totalInCategory: categoryFonts.length,
1157
- remainingItems
1158
- });
1145
+ // console.log('🔍 [FontManager] Checking remaining fonts:', {
1146
+ // category,
1147
+ // currentIndex,
1148
+ // totalInCategory: categoryFonts.length,
1149
+ // remainingItems
1150
+ // });
1159
1151
  // Only return true if we have more items in this category
1160
1152
  return remainingItems > 0;
1161
1153
  }
@@ -1204,7 +1196,7 @@ class FontManager {
1204
1196
  fonts: this.catalog.fonts.filter(font => font.family !== family || font.category !== 'Mine'),
1205
1197
  };
1206
1198
  }
1207
- console.log('✅ [FontManager] Custom font removed:', family);
1199
+ // console.log('✅ [FontManager] Custom font removed:', family);
1208
1200
  }
1209
1201
  }
1210
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 cache
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
- // Cache the complete vector list immediately
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
- // Preload vectors for each category
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
- // Preload the vectors
125
- await Promise.all(categoryVectors.map(async (vector) => {
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 caching complete vector list:', 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 response = await fetch('/svgs.json');
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 cache
306
+ * Saves vector list to cache (avoids writing 1.2MB JSON to localStorage)
324
307
  */
325
308
  saveVectorListToCache(vectors) {
326
309
  try {
327
- const cacheData = {
328
- timestamp: Date.now(),
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
- console.error('❌ [VectorManager] Error caching vector list:', error);
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
- try {
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
@@ -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
- // Add passive event listener support globally
2
- if (typeof window !== 'undefined') {
3
- // Save the original addEventListener
4
- const originalAddEventListener = EventTarget.prototype.addEventListener;
5
- // Override addEventListener
6
- EventTarget.prototype.addEventListener = function (type, listener, options) {
7
- // Force passive for touch and wheel events
8
- if (type === 'touchstart' || type === 'touchmove' || type === 'wheel') {
9
- let newOptions = options;
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
- normalizedColor,
19
- alpha,
20
- originalColor: color
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
- existing: normalizedExisting,
29
- new: normalizedColor,
30
- existingAlpha: c.alpha,
31
- newAlpha: alpha,
32
- alphaMatch,
33
- colorsMatch: normalizedExisting === normalizedColor
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