@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.
- package/dist/nocturna-wheel.bundle.js +148 -81
- package/dist/nocturna-wheel.bundle.js.map +1 -1
- package/dist/nocturna-wheel.es.js +148 -81
- package/dist/nocturna-wheel.es.js.map +1 -1
- package/dist/nocturna-wheel.min.js +1 -1
- package/dist/nocturna-wheel.min.js.map +1 -1
- package/dist/nocturna-wheel.umd.js +148 -81
- package/dist/nocturna-wheel.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -83,47 +83,16 @@ class ServiceRegistry {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* Gets
|
|
87
|
-
*
|
|
88
|
-
*
|
|
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(
|
|
91
|
+
static getIconProvider() {
|
|
91
92
|
if (!this.has('iconProvider')) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
//
|
|
140
|
-
this
|
|
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
|
-
|
|
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-
|
|
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
|
-
|
|
1966
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2072
|
+
const basePath = this.options.assetBasePath || this.assetBasePath || './assets/';
|
|
2073
|
+
iconHref = `${basePath}svg/zodiac/zodiac-sign-${signName}.svg`;
|
|
2081
2074
|
}
|
|
2082
2075
|
|
|
2083
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
//
|
|
5625
|
-
|
|
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
|
|
5674
|
+
// Initialize with inline data if available
|
|
5628
5675
|
if (IconData && Object.keys(IconData.planets || {}).length > 0) {
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
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
|
-
//
|
|
5735
|
-
|
|
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();
|