@eaprelsky/nocturna-wheel 3.0.0 → 3.0.2

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.
@@ -83,47 +83,16 @@ class ServiceRegistry {
83
83
  }
84
84
 
85
85
  /**
86
- * Gets or creates an IconProvider instance
87
- * @param {string} basePath - Optional base path for SVG assets
88
- * @returns {Object} The IconProvider instance
86
+ * Gets the IconProvider instance
87
+ * NOTE: IconProvider should be registered externally before use
88
+ * This method only retrieves, does not create
89
+ * @returns {Object|undefined} The IconProvider instance if registered
89
90
  */
90
- static getIconProvider(basePath = './assets/svg/zodiac/') {
91
+ static getIconProvider() {
91
92
  if (!this.has('iconProvider')) {
92
- // Create a simple icon provider
93
- const iconProvider = {
94
- basePath: basePath,
95
-
96
- getPlanetIconPath(planetName) {
97
- return `${this.basePath}zodiac-planet-${planetName.toLowerCase()}.svg`;
98
- },
99
-
100
- getZodiacIconPath(signName) {
101
- return `${this.basePath}zodiac-sign-${signName.toLowerCase()}.svg`;
102
- },
103
-
104
- getAspectIconPath(aspectType) {
105
- return `${this.basePath}zodiac-aspect-${aspectType.toLowerCase()}.svg`;
106
- },
107
-
108
- createTextFallback(svgUtils, options, text) {
109
- const { x, y, size = '16px', color = '#000000', className = 'icon-fallback' } = options;
110
-
111
- const textElement = svgUtils.createSVGElement("text", {
112
- x: x,
113
- y: y,
114
- 'text-anchor': 'middle',
115
- 'dominant-baseline': 'middle',
116
- 'font-size': size,
117
- 'class': className,
118
- 'fill': color
119
- });
120
-
121
- textElement.textContent = text;
122
- return textElement;
123
- }
124
- };
125
-
126
- this.register('iconProvider', iconProvider);
93
+ console.warn('ServiceRegistry: IconProvider not registered. Icons may not work correctly.');
94
+ console.warn('ServiceRegistry: This should be initialized in main.js with inline IconData.');
95
+ return null;
127
96
  }
128
97
  return this.get('iconProvider');
129
98
  }
@@ -136,8 +105,8 @@ class ServiceRegistry {
136
105
  // Initialize SvgUtils
137
106
  this.getSvgUtils();
138
107
 
139
- // Initialize IconProvider with the assets base path
140
- this.getIconProvider(options.assetBasePath || './assets/svg/zodiac/');
108
+ // Note: IconProvider should be registered externally in main.js
109
+ // with inline IconData before calling this method
141
110
 
142
111
  console.log("ServiceRegistry: Core services initialized");
143
112
  }
@@ -153,17 +122,6 @@ class ServiceRegistry {
153
122
  * 2. External mode: Uses external file paths (for custom icons)
154
123
  */
155
124
 
156
- // Try to import IconData if available (after build)
157
- let InlineIconData = null;
158
- try {
159
- // This will be replaced by rollup during build
160
- // During development or if IconData doesn't exist, this will fail gracefully
161
- InlineIconData = null; // Will be set up after IconData.js is generated
162
- } catch (e) {
163
- // IconData not available yet
164
- InlineIconData = null;
165
- }
166
-
167
125
  class IconProvider {
168
126
  /**
169
127
  * Constructor
@@ -184,6 +142,9 @@ class IconProvider {
184
142
 
185
143
  // Lazy-load IconData on first use
186
144
  this.inlineData = null;
145
+
146
+ // Track if warning was already shown (to avoid spam)
147
+ this._warnedAboutMissingData = false;
187
148
  }
188
149
 
189
150
  /**
@@ -191,9 +152,6 @@ class IconProvider {
191
152
  * @private
192
153
  */
193
154
  _getInlineData() {
194
- if (!this.inlineData && InlineIconData) {
195
- this.inlineData = InlineIconData;
196
- }
197
155
  return this.inlineData;
198
156
  }
199
157
 
@@ -203,7 +161,11 @@ class IconProvider {
203
161
  */
204
162
  setInlineData(iconData) {
205
163
  this.inlineData = iconData;
206
- InlineIconData = iconData;
164
+ console.log('IconProvider.setInlineData(): Data loaded successfully',
165
+ 'planets:', Object.keys(iconData?.planets || {}).length,
166
+ 'signs:', Object.keys(iconData?.signs || {}).length,
167
+ 'aspects:', Object.keys(iconData?.aspects || {}).length
168
+ );
207
169
  }
208
170
 
209
171
  /**
@@ -224,6 +186,16 @@ class IconProvider {
224
186
  const inlineData = this._getInlineData();
225
187
  if (inlineData?.planets?.[name]) {
226
188
  return inlineData.planets[name];
189
+ } else {
190
+ // Debug: log when inline data is not available (only once)
191
+ if (!this._warnedAboutMissingData) {
192
+ this._warnedAboutMissingData = true;
193
+ if (!inlineData) {
194
+ console.warn(`IconProvider: Inline data not loaded, falling back to external paths. Call setInlineData() to load inline icons.`);
195
+ } else if (!inlineData.planets) {
196
+ console.warn(`IconProvider: Inline data missing 'planets' category`);
197
+ }
198
+ }
227
199
  }
228
200
  }
229
201
 
@@ -315,7 +287,7 @@ class IconProvider {
315
287
  /**
316
288
  * IconData.js
317
289
  * Auto-generated module containing inline SVG icons as data URLs
318
- * Generated at: 2025-11-13T13:46:12.044Z
290
+ * Generated at: 2025-11-14T16:02:20.923Z
319
291
  *
320
292
  * This file is automatically generated by the build process.
321
293
  * Do not edit manually - changes will be overwritten.
@@ -1962,11 +1934,18 @@ class ZodiacRenderer extends BaseRenderer {
1962
1934
  */
1963
1935
  constructor(options) {
1964
1936
  super(options);
1965
- if (!options.assetBasePath) {
1966
- throw new Error("ZodiacRenderer: Missing required option assetBasePath");
1937
+
1938
+ // Store the icon provider
1939
+ this.iconProvider = options.iconProvider;
1940
+
1941
+ // assetBasePath is required only if IconProvider is not available
1942
+ if (!options.assetBasePath && !this.iconProvider) {
1943
+ throw new Error("ZodiacRenderer: Missing required option assetBasePath or iconProvider");
1967
1944
  }
1968
-
1969
- this.iconProvider = options.iconProvider; // Store the icon provider
1945
+
1946
+ // Set default assetBasePath if not provided (for backward compatibility)
1947
+ this.assetBasePath = options.assetBasePath || './assets/';
1948
+
1970
1949
  this.signIconRadius = (this.outerRadius + this.middleRadius) / 2;
1971
1950
  this.signIconSize = 30;
1972
1951
  }
@@ -2007,10 +1986,21 @@ class ZodiacRenderer extends BaseRenderer {
2007
1986
  ];
2008
1987
 
2009
1988
  circles.forEach(circleData => {
1989
+ // Determine stroke color and width based on circle type
1990
+ let strokeColor = "#999";
1991
+ let strokeWidth = "0.5";
1992
+ if (circleData.class === "chart-outer-circle") {
1993
+ strokeColor = "#666";
1994
+ strokeWidth = "1";
1995
+ }
1996
+
2010
1997
  const circle = this.svgUtils.createSVGElement("circle", {
2011
1998
  cx: this.centerX,
2012
1999
  cy: this.centerY,
2013
2000
  r: circleData.r,
2001
+ fill: "transparent", // Explicitly set transparent fill to avoid default black
2002
+ stroke: strokeColor, // Explicitly set stroke to ensure visibility
2003
+ "stroke-width": strokeWidth, // Explicitly set stroke width
2014
2004
  class: `zodiac-element ${circleData.class}` // Add base class
2015
2005
  });
2016
2006
  parentGroup.appendChild(circle);
@@ -2045,6 +2035,8 @@ class ZodiacRenderer extends BaseRenderer {
2045
2035
  y1: point1.y,
2046
2036
  x2: point2.x,
2047
2037
  y2: point2.y,
2038
+ stroke: "#999", // Explicitly set stroke to ensure visibility
2039
+ "stroke-width": "0.75", // Explicitly set stroke width
2048
2040
  class: `zodiac-element zodiac-division-line ${specialClass}`
2049
2041
  });
2050
2042
 
@@ -2077,10 +2069,17 @@ class ZodiacRenderer extends BaseRenderer {
2077
2069
  iconHref = this.iconProvider.getZodiacIconPath(signName);
2078
2070
  } else {
2079
2071
  // Fallback to old path construction
2080
- iconHref = `${this.options.assetBasePath}svg/zodiac/zodiac-sign-${signName}.svg`;
2072
+ const basePath = this.options.assetBasePath || this.assetBasePath || './assets/';
2073
+ iconHref = `${basePath}svg/zodiac/zodiac-sign-${signName}.svg`;
2081
2074
  }
2082
2075
 
2083
- console.log(`Loading zodiac sign: ${iconHref}`);
2076
+ // Log icon path for debugging (only log first time for each sign to avoid spam)
2077
+ if (!this._loggedSigns) this._loggedSigns = {};
2078
+ if (!this._loggedSigns[signName]) {
2079
+ console.log(`ZodiacRenderer: Loading sign '${signName}':`,
2080
+ iconHref.startsWith('data:') ? 'inline data URL' : iconHref);
2081
+ this._loggedSigns[signName] = true;
2082
+ }
2084
2083
 
2085
2084
  const icon = this.svgUtils.createSVGElement("image", {
2086
2085
  x: point.x - this.signIconSize / 2, // Offset to center the icon
@@ -2229,12 +2228,34 @@ class HouseRenderer extends BaseRenderer {
2229
2228
  const innerPoint = this.svgUtils.pointOnCircle(this.centerX, this.centerY, this.innerRadius, angle);
2230
2229
  const middlePoint = this.svgUtils.pointOnCircle(this.centerX, this.centerY, this.middleRadius, angle);
2231
2230
 
2231
+ // Determine stroke color and width based on line type
2232
+ let innerStrokeColor = "#999";
2233
+ let innerStrokeWidth = "0.75";
2234
+
2235
+ let outerStrokeColor = "#999";
2236
+ let outerStrokeWidth = "0.75";
2237
+ let outerStrokeDasharray = null;
2238
+
2239
+ if (axisClass.includes('axis')) {
2240
+ // Cardinal points (ASC, DSC, IC, MC) - solid, darker
2241
+ innerStrokeColor = "#555";
2242
+ innerStrokeWidth = "1";
2243
+ outerStrokeColor = "#555";
2244
+ outerStrokeWidth = "1";
2245
+ // Axes are always solid
2246
+ } else {
2247
+ // Regular lines - outer lines are dashed
2248
+ outerStrokeDasharray = "2,2";
2249
+ }
2250
+
2232
2251
  // Create line from inner to middle circle
2233
2252
  const innerLine = this.svgUtils.createSVGElement("line", {
2234
2253
  x1: innerPoint.x,
2235
2254
  y1: innerPoint.y,
2236
2255
  x2: middlePoint.x,
2237
2256
  y2: middlePoint.y,
2257
+ stroke: innerStrokeColor, // Explicitly set stroke to ensure visibility
2258
+ "stroke-width": innerStrokeWidth, // Explicitly set stroke width
2238
2259
  class: `house-element house-division-line ${axisClass}`
2239
2260
  });
2240
2261
 
@@ -2256,13 +2277,21 @@ class HouseRenderer extends BaseRenderer {
2256
2277
  const extendedPoint = this.svgUtils.pointOnCircle(this.centerX, this.centerY, this.extendedRadius, angle);
2257
2278
 
2258
2279
  // Create line from outer circle to extended point
2259
- const outerLine = this.svgUtils.createSVGElement("line", {
2280
+ const outerLineAttrs = {
2260
2281
  x1: outerPoint.x,
2261
2282
  y1: outerPoint.y,
2262
2283
  x2: extendedPoint.x,
2263
2284
  y2: extendedPoint.y,
2285
+ stroke: outerStrokeColor, // Explicitly set stroke to ensure visibility
2286
+ "stroke-width": outerStrokeWidth, // Explicitly set stroke width
2264
2287
  class: `house-element house-division-line outer ${axisClass}`
2265
- });
2288
+ };
2289
+
2290
+ if (outerStrokeDasharray) {
2291
+ outerLineAttrs["stroke-dasharray"] = outerStrokeDasharray;
2292
+ }
2293
+
2294
+ const outerLine = this.svgUtils.createSVGElement("line", outerLineAttrs);
2266
2295
 
2267
2296
  // Ensure cardinal points render above zodiac lines
2268
2297
  if (axisClass.includes('axis')) {
@@ -2399,12 +2428,17 @@ class BasePlanetRenderer extends BaseRenderer {
2399
2428
  */
2400
2429
  constructor(options) {
2401
2430
  super(options);
2402
- if (!options.assetBasePath) {
2403
- throw new Error(`${this.constructor.name}: Missing required option assetBasePath`);
2404
- }
2405
2431
 
2406
2432
  // Store the icon provider
2407
2433
  this.iconProvider = options.iconProvider;
2434
+
2435
+ // assetBasePath is required only if IconProvider is not available
2436
+ if (!options.assetBasePath && !this.iconProvider) {
2437
+ throw new Error(`${this.constructor.name}: Missing required option assetBasePath or iconProvider`);
2438
+ }
2439
+
2440
+ // Set default assetBasePath if not provided (for backward compatibility)
2441
+ this.assetBasePath = options.assetBasePath || './assets/';
2408
2442
  }
2409
2443
 
2410
2444
  /**
@@ -2506,7 +2540,8 @@ class PlanetSymbolRenderer extends BasePlanetRenderer {
2506
2540
  iconPath = this.iconProvider.getPlanetIconPath(planet.name);
2507
2541
  } else {
2508
2542
  // Fallback to old path construction if IconProvider is not available
2509
- iconPath = `${this.options.assetBasePath}svg/zodiac/zodiac-planet-${planet.name.toLowerCase()}.svg`;
2543
+ const basePath = this.options.assetBasePath || this.assetBasePath || './assets/';
2544
+ iconPath = `${basePath}svg/zodiac/zodiac-planet-${planet.name.toLowerCase()}.svg`;
2510
2545
  }
2511
2546
 
2512
2547
  // Calculate top-left position of the icon (centered on the calculated point)
@@ -3508,7 +3543,7 @@ class ClientSideAspectRenderer extends BaseRenderer { // No longer extends IAspe
3508
3543
  this.renderedAspects = []; // Store calculated aspects
3509
3544
  this._aspectCacheKey = null; // Cache key for aspect calculations
3510
3545
  this._aspectCache = []; // Cached aspect results
3511
- this.assetBasePath = options.assetBasePath || ''; // Store asset base path
3546
+ this.assetBasePath = options.assetBasePath || './assets/'; // Store asset base path with fallback
3512
3547
  this.iconProvider = options.iconProvider; // Store the icon provider
3513
3548
 
3514
3549
  // Define major aspects and their angles (can be overridden/extended by config)
@@ -4037,7 +4072,12 @@ class RendererFactory {
4037
4072
  this.config = config;
4038
4073
  this.svgNS = svgNS;
4039
4074
  this.svgUtils = ServiceRegistry.getSvgUtils();
4040
- this.iconProvider = ServiceRegistry.getIconProvider(config.assets?.basePath);
4075
+ this.iconProvider = ServiceRegistry.getIconProvider();
4076
+
4077
+ // If IconProvider is null, log error for debugging
4078
+ if (!this.iconProvider) {
4079
+ console.error('RendererFactory: IconProvider not available. Icons will not render correctly.');
4080
+ }
4041
4081
  }
4042
4082
 
4043
4083
  /**
@@ -5341,6 +5381,9 @@ class ChartRenderer {
5341
5381
  cx: centerX,
5342
5382
  cy: centerY,
5343
5383
  r: radius,
5384
+ fill: "transparent", // Explicitly set transparent fill to avoid default black
5385
+ stroke: "#999", // Explicitly set stroke to ensure visibility
5386
+ "stroke-width": "0.5", // Explicitly set stroke width
5344
5387
  class: 'zodiac-element chart-innermost-circle'
5345
5388
  });
5346
5389
  zodiacGroup.appendChild(innermostCircle);
@@ -5621,17 +5664,31 @@ class WheelChart {
5621
5664
  * See examples/factory-injection-example.js for more advanced usage patterns.
5622
5665
  */
5623
5666
 
5624
- // Initialize core services immediately
5625
- ServiceRegistry.initializeServices();
5667
+ // CRITICAL: Register IconProvider BEFORE initializing other services
5668
+ // This ensures renderers get the inline-capable provider, not a legacy stub
5669
+ const iconProvider = new IconProvider({
5670
+ useInline: true,
5671
+ basePath: './assets/svg/zodiac/' // Fallback for external mode
5672
+ });
5626
5673
 
5627
- // Initialize IconProvider with inline data if available
5674
+ // Initialize with inline data if available
5628
5675
  if (IconData && Object.keys(IconData.planets || {}).length > 0) {
5629
- const iconProvider = ServiceRegistry.getIconProvider();
5630
- if (iconProvider && typeof iconProvider.setInlineData === 'function') {
5631
- iconProvider.setInlineData(IconData);
5632
- }
5676
+ iconProvider.setInlineData(IconData);
5677
+ console.log('IconProvider: Initialized with inline icons -',
5678
+ 'Planets:', Object.keys(IconData.planets).length,
5679
+ 'Signs:', Object.keys(IconData.signs).length,
5680
+ 'Aspects:', Object.keys(IconData.aspects).length
5681
+ );
5682
+ } else {
5683
+ console.warn('IconProvider: IconData not loaded, will use external paths');
5633
5684
  }
5634
5685
 
5686
+ // Register IconProvider BEFORE initializing services
5687
+ ServiceRegistry.register('iconProvider', iconProvider);
5688
+
5689
+ // Now initialize other core services
5690
+ ServiceRegistry.initializeServices();
5691
+
5635
5692
  // Library version
5636
5693
  const VERSION = '0.2.0';
5637
5694
 
@@ -5731,11 +5788,21 @@ function cleanup() {
5731
5788
  }
5732
5789
  }
5733
5790
 
5734
- // Initialize the chart when the DOM is ready
5735
- document.addEventListener('DOMContentLoaded', initChart);
5791
+ // Auto-initialization is DISABLED in production builds to prevent conflicts.
5792
+ // This demo code should only run in development mode with Vite dev server.
5793
+ // In production, users explicitly create their own chart instances.
5736
5794
 
5737
- // Handle hot module replacement for Vite
5795
+ // Handle hot module replacement for Vite (development only)
5738
5796
  if (import.meta.hot) {
5797
+ // Initialize the chart when the DOM is ready (ONLY in development)
5798
+ document.addEventListener('DOMContentLoaded', () => {
5799
+ const container = document.getElementById('chart-container');
5800
+ if (container && container.children.length === 0) {
5801
+ console.log('DEV MODE: Auto-initializing demo chart');
5802
+ initChart();
5803
+ }
5804
+ });
5805
+
5739
5806
  import.meta.hot.accept((newModule) => {
5740
5807
  console.log('HMR update for main.js');
5741
5808
  cleanup();