@widgetic/editor 4.0.2 → 4.0.4

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 (35) hide show
  1. package/dist/components/MockWidget.svelte +1 -1
  2. package/dist/components/WidgetPreview.svelte +347 -97
  3. package/dist/components/WidgetPreview.svelte.d.ts +5 -0
  4. package/dist/components/editors/EmbedEditor.svelte +1 -1
  5. package/dist/components/editors/PropsEditor.svelte +173 -148
  6. package/dist/components/ic/BrowserInputController.svelte +14 -14
  7. package/dist/components/ic/CheckboxInputController.svelte +1 -1
  8. package/dist/components/ic/ColorPickerInputController.svelte +37 -37
  9. package/dist/components/ic/DatePickerInputController.svelte +6 -6
  10. package/dist/components/ic/DropdownInputController.svelte +1 -1
  11. package/dist/components/ic/FontInputController.svelte +136 -63
  12. package/dist/components/ic/FontInputController.svelte.d.ts +3 -1
  13. package/dist/components/ic/NumberInputController.svelte +37 -37
  14. package/dist/components/ic/RadioGroupInputController.svelte +1 -1
  15. package/dist/components/ic/SliderRangeInputController.svelte +1 -1
  16. package/dist/components/ic/SwitchInputController.svelte +1 -1
  17. package/dist/components/ic/TextAreaInputController.svelte +23 -23
  18. package/dist/components/ic/TextAreaPreviewInputController.svelte +2 -2
  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/stores/userSession.d.ts +1 -1
  24. package/dist/stores/userSession.js +17 -2
  25. package/dist/utils/FontManager.d.ts +1 -1
  26. package/dist/utils/FontManager.js +75 -102
  27. package/dist/utils/VectorManager.d.ts +3 -1
  28. package/dist/utils/VectorManager.js +30 -70
  29. package/dist/utils/colorTransparency.js +3 -3
  30. package/dist/utils/fontUtils.js +1 -1
  31. package/dist/utils/passiveEvents.d.ts +5 -0
  32. package/dist/utils/passiveEvents.js +9 -18
  33. package/dist/utils/recentColors.js +15 -15
  34. package/dist/utils/vectorUtils.js +1 -1
  35. 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
- /** 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
@@ -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: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/*, ' +
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 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. ' +
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
- // Preload initial fonts for each category
299
+ // Index initial fonts for each category without blocking startup
275
300
  const categories = ['Serif', 'Sans Serif', 'Script', 'Other'];
276
- // Preload fonts for each category
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
- // Preload the fonts by inserting their stylesheets
283
- await Promise.all(categoryFonts.map(async (font) => {
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
- // Define initial fonts that must be loaded (excluding skipped fonts)
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
- category,
1174
- currentIndex,
1175
- totalInCategory: categoryFonts.length,
1176
- remainingItems
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 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widgetic/editor",
3
- "version": "4.0.2",
3
+ "version": "4.0.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",