@xivdyetools/core 1.3.7

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 (103) hide show
  1. package/LICENSE +37 -0
  2. package/README.md +400 -0
  3. package/dist/constants/index.d.ts +56 -0
  4. package/dist/constants/index.d.ts.map +1 -0
  5. package/dist/constants/index.js +103 -0
  6. package/dist/constants/index.js.map +1 -0
  7. package/dist/data/colors_xiv.json +3130 -0
  8. package/dist/data/locales/de.json +231 -0
  9. package/dist/data/locales/en.json +231 -0
  10. package/dist/data/locales/fr.json +231 -0
  11. package/dist/data/locales/ja.json +231 -0
  12. package/dist/data/locales/ko.json +233 -0
  13. package/dist/data/locales/zh.json +233 -0
  14. package/dist/data/presets.json +390 -0
  15. package/dist/index.d.ts +16 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +18 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/services/APIService.d.ts +246 -0
  20. package/dist/services/APIService.d.ts.map +1 -0
  21. package/dist/services/APIService.js +499 -0
  22. package/dist/services/APIService.js.map +1 -0
  23. package/dist/services/ColorService.d.ts +146 -0
  24. package/dist/services/ColorService.d.ts.map +1 -0
  25. package/dist/services/ColorService.js +209 -0
  26. package/dist/services/ColorService.js.map +1 -0
  27. package/dist/services/DyeService.d.ts +230 -0
  28. package/dist/services/DyeService.d.ts.map +1 -0
  29. package/dist/services/DyeService.js +326 -0
  30. package/dist/services/DyeService.js.map +1 -0
  31. package/dist/services/LocalizationService.d.ts +338 -0
  32. package/dist/services/LocalizationService.d.ts.map +1 -0
  33. package/dist/services/LocalizationService.js +449 -0
  34. package/dist/services/LocalizationService.js.map +1 -0
  35. package/dist/services/PaletteService.d.ts +137 -0
  36. package/dist/services/PaletteService.d.ts.map +1 -0
  37. package/dist/services/PaletteService.js +349 -0
  38. package/dist/services/PaletteService.js.map +1 -0
  39. package/dist/services/PresetService.d.ts +196 -0
  40. package/dist/services/PresetService.d.ts.map +1 -0
  41. package/dist/services/PresetService.js +261 -0
  42. package/dist/services/PresetService.js.map +1 -0
  43. package/dist/services/color/ColorAccessibility.d.ts +39 -0
  44. package/dist/services/color/ColorAccessibility.d.ts.map +1 -0
  45. package/dist/services/color/ColorAccessibility.js +71 -0
  46. package/dist/services/color/ColorAccessibility.js.map +1 -0
  47. package/dist/services/color/ColorConverter.d.ts +146 -0
  48. package/dist/services/color/ColorConverter.d.ts.map +1 -0
  49. package/dist/services/color/ColorConverter.js +393 -0
  50. package/dist/services/color/ColorConverter.js.map +1 -0
  51. package/dist/services/color/ColorManipulator.d.ts +36 -0
  52. package/dist/services/color/ColorManipulator.d.ts.map +1 -0
  53. package/dist/services/color/ColorManipulator.js +56 -0
  54. package/dist/services/color/ColorManipulator.js.map +1 -0
  55. package/dist/services/color/ColorblindnessSimulator.d.ts +35 -0
  56. package/dist/services/color/ColorblindnessSimulator.d.ts.map +1 -0
  57. package/dist/services/color/ColorblindnessSimulator.js +110 -0
  58. package/dist/services/color/ColorblindnessSimulator.js.map +1 -0
  59. package/dist/services/dye/DyeDatabase.d.ts +131 -0
  60. package/dist/services/dye/DyeDatabase.d.ts.map +1 -0
  61. package/dist/services/dye/DyeDatabase.js +367 -0
  62. package/dist/services/dye/DyeDatabase.js.map +1 -0
  63. package/dist/services/dye/DyeSearch.d.ts +55 -0
  64. package/dist/services/dye/DyeSearch.d.ts.map +1 -0
  65. package/dist/services/dye/DyeSearch.js +196 -0
  66. package/dist/services/dye/DyeSearch.js.map +1 -0
  67. package/dist/services/dye/HarmonyGenerator.d.ts +110 -0
  68. package/dist/services/dye/HarmonyGenerator.d.ts.map +1 -0
  69. package/dist/services/dye/HarmonyGenerator.js +221 -0
  70. package/dist/services/dye/HarmonyGenerator.js.map +1 -0
  71. package/dist/services/localization/LocaleLoader.d.ts +38 -0
  72. package/dist/services/localization/LocaleLoader.d.ts.map +1 -0
  73. package/dist/services/localization/LocaleLoader.js +83 -0
  74. package/dist/services/localization/LocaleLoader.js.map +1 -0
  75. package/dist/services/localization/LocaleRegistry.d.ts +73 -0
  76. package/dist/services/localization/LocaleRegistry.d.ts.map +1 -0
  77. package/dist/services/localization/LocaleRegistry.js +84 -0
  78. package/dist/services/localization/LocaleRegistry.js.map +1 -0
  79. package/dist/services/localization/TranslationProvider.d.ts +157 -0
  80. package/dist/services/localization/TranslationProvider.d.ts.map +1 -0
  81. package/dist/services/localization/TranslationProvider.js +289 -0
  82. package/dist/services/localization/TranslationProvider.js.map +1 -0
  83. package/dist/types/index.d.ts +409 -0
  84. package/dist/types/index.d.ts.map +1 -0
  85. package/dist/types/index.js +87 -0
  86. package/dist/types/index.js.map +1 -0
  87. package/dist/types/logger.d.ts +84 -0
  88. package/dist/types/logger.d.ts.map +1 -0
  89. package/dist/types/logger.js +54 -0
  90. package/dist/types/logger.js.map +1 -0
  91. package/dist/utils/index.d.ts +441 -0
  92. package/dist/utils/index.d.ts.map +1 -0
  93. package/dist/utils/index.js +577 -0
  94. package/dist/utils/index.js.map +1 -0
  95. package/dist/utils/kd-tree.d.ts +76 -0
  96. package/dist/utils/kd-tree.d.ts.map +1 -0
  97. package/dist/utils/kd-tree.js +195 -0
  98. package/dist/utils/kd-tree.js.map +1 -0
  99. package/dist/version.d.ts +11 -0
  100. package/dist/version.d.ts.map +1 -0
  101. package/dist/version.js +11 -0
  102. package/dist/version.js.map +1 -0
  103. package/package.json +84 -0
@@ -0,0 +1,349 @@
1
+ /**
2
+ * @xivdyetools/core - Palette Extraction Service
3
+ *
4
+ * Extracts dominant colors from pixel data using K-means clustering.
5
+ * Matches extracted colors to closest FFXIV dyes.
6
+ *
7
+ * @module services/PaletteService
8
+ * @example
9
+ * ```typescript
10
+ * import { PaletteService, DyeService, dyeDatabase } from '@xivdyetools/core';
11
+ *
12
+ * const paletteService = new PaletteService();
13
+ * const dyeService = new DyeService(dyeDatabase);
14
+ *
15
+ * // Extract 4 dominant colors from pixel data
16
+ * const palette = paletteService.extractPalette(pixels, 4);
17
+ *
18
+ * // Extract and match to dyes in one step
19
+ * const matches = paletteService.extractAndMatchPalette(pixels, 4, dyeService);
20
+ * ```
21
+ */
22
+ import { NoOpLogger } from '../types/index.js';
23
+ import { ColorService } from './ColorService.js';
24
+ // ============================================================================
25
+ // K-Means Clustering Implementation
26
+ // ============================================================================
27
+ /**
28
+ * Calculate Euclidean distance between two RGB colors
29
+ */
30
+ function rgbDistance(a, b) {
31
+ const dr = a.r - b.r;
32
+ const dg = a.g - b.g;
33
+ const db = a.b - b.b;
34
+ return Math.sqrt(dr * dr + dg * dg + db * db);
35
+ }
36
+ /**
37
+ * Calculate the mean of an array of RGB colors
38
+ */
39
+ function rgbMean(colors) {
40
+ if (colors.length === 0) {
41
+ return { r: 0, g: 0, b: 0 };
42
+ }
43
+ let sumR = 0;
44
+ let sumG = 0;
45
+ let sumB = 0;
46
+ for (const c of colors) {
47
+ sumR += c.r;
48
+ sumG += c.g;
49
+ sumB += c.b;
50
+ }
51
+ return {
52
+ r: Math.round(sumR / colors.length),
53
+ g: Math.round(sumG / colors.length),
54
+ b: Math.round(sumB / colors.length),
55
+ };
56
+ }
57
+ /**
58
+ * K-means++ initialization for better starting centroids
59
+ * Selects initial centroids that are well-distributed
60
+ * CORE-PERF-003: Optimized from O(n*k²) to O(n*k) by caching minimum distances
61
+ */
62
+ function kMeansPlusPlusInit(pixels, k) {
63
+ if (pixels.length === 0 || k <= 0) {
64
+ return [];
65
+ }
66
+ const centroids = [];
67
+ // First centroid: random pixel
68
+ const firstIndex = Math.floor(Math.random() * pixels.length);
69
+ centroids.push({ ...pixels[firstIndex] });
70
+ // CORE-PERF-003: Cache minimum distances to avoid O(k) inner loop
71
+ // Initialize with distance to first centroid
72
+ const minDistances = new Array(pixels.length);
73
+ for (let j = 0; j < pixels.length; j++) {
74
+ minDistances[j] = rgbDistance(pixels[j], centroids[0]);
75
+ }
76
+ // Remaining centroids: weighted probability by distance squared
77
+ for (let i = 1; i < k; i++) {
78
+ // Calculate total distance (squared) for probability distribution
79
+ let totalDistanceSquared = 0;
80
+ for (let j = 0; j < pixels.length; j++) {
81
+ totalDistanceSquared += minDistances[j] * minDistances[j];
82
+ }
83
+ // Select next centroid with probability proportional to distance squared
84
+ let selectedIndex = 0;
85
+ if (totalDistanceSquared === 0) {
86
+ // All remaining pixels are duplicates of centroids
87
+ selectedIndex = Math.floor(Math.random() * pixels.length);
88
+ }
89
+ else {
90
+ let threshold = Math.random() * totalDistanceSquared;
91
+ for (let j = 0; j < pixels.length; j++) {
92
+ threshold -= minDistances[j] * minDistances[j];
93
+ if (threshold <= 0) {
94
+ selectedIndex = j;
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ centroids.push({ ...pixels[selectedIndex] });
100
+ // CORE-PERF-003: Only compute distance to the NEW centroid and update minimums
101
+ // This reduces complexity from O(n*k) per iteration to O(n) per iteration
102
+ const newCentroid = centroids[centroids.length - 1];
103
+ for (let j = 0; j < pixels.length; j++) {
104
+ const distToNew = rgbDistance(pixels[j], newCentroid);
105
+ if (distToNew < minDistances[j]) {
106
+ minDistances[j] = distToNew;
107
+ }
108
+ }
109
+ }
110
+ return centroids;
111
+ }
112
+ /**
113
+ * Assign each pixel to its nearest centroid
114
+ * Returns array of cluster indices and the clusters themselves
115
+ */
116
+ function assignToClusters(pixels, centroids) {
117
+ const assignments = new Array(pixels.length);
118
+ const clusters = centroids.map(() => []);
119
+ for (let i = 0; i < pixels.length; i++) {
120
+ const pixel = pixels[i];
121
+ let minDist = Infinity;
122
+ let nearestCluster = 0;
123
+ for (let j = 0; j < centroids.length; j++) {
124
+ const dist = rgbDistance(pixel, centroids[j]);
125
+ if (dist < minDist) {
126
+ minDist = dist;
127
+ nearestCluster = j;
128
+ }
129
+ }
130
+ assignments[i] = nearestCluster;
131
+ clusters[nearestCluster].push(pixel);
132
+ }
133
+ return { assignments, clusters };
134
+ }
135
+ /**
136
+ * Update centroids to be the mean of their clusters
137
+ * Returns new centroids and the maximum movement distance
138
+ */
139
+ function updateCentroids(centroids, clusters) {
140
+ const newCentroids = [];
141
+ let maxMovement = 0;
142
+ for (let i = 0; i < centroids.length; i++) {
143
+ const cluster = clusters[i];
144
+ if (cluster.length === 0) {
145
+ // Empty cluster: keep old centroid
146
+ newCentroids.push({ ...centroids[i] });
147
+ }
148
+ else {
149
+ const newCentroid = rgbMean(cluster);
150
+ const movement = rgbDistance(centroids[i], newCentroid);
151
+ if (movement > maxMovement) {
152
+ maxMovement = movement;
153
+ }
154
+ newCentroids.push(newCentroid);
155
+ }
156
+ }
157
+ return { newCentroids, maxMovement };
158
+ }
159
+ /**
160
+ * Run K-means clustering on pixel data
161
+ */
162
+ function kMeansClustering(pixels, k, maxIterations, convergenceThreshold) {
163
+ if (pixels.length === 0) {
164
+ return { centroids: [], clusterSizes: [] };
165
+ }
166
+ // Limit k to number of unique pixels
167
+ const effectiveK = Math.min(k, pixels.length);
168
+ // Initialize centroids using K-means++
169
+ let centroids = kMeansPlusPlusInit(pixels, effectiveK);
170
+ // Iterate until convergence or max iterations
171
+ for (let iter = 0; iter < maxIterations; iter++) {
172
+ // Assign pixels to clusters
173
+ const { clusters } = assignToClusters(pixels, centroids);
174
+ // Update centroids
175
+ const { newCentroids, maxMovement } = updateCentroids(centroids, clusters);
176
+ centroids = newCentroids;
177
+ // Check for convergence
178
+ if (maxMovement < convergenceThreshold) {
179
+ break;
180
+ }
181
+ }
182
+ // Final assignment to get cluster sizes
183
+ const { clusters } = assignToClusters(pixels, centroids);
184
+ const clusterSizes = clusters.map((c) => c.length);
185
+ return { centroids, clusterSizes };
186
+ }
187
+ // ============================================================================
188
+ // PaletteService Class
189
+ // ============================================================================
190
+ /**
191
+ * Service for extracting color palettes from images
192
+ *
193
+ * Uses K-means clustering to find dominant colors, then matches
194
+ * them to the closest FFXIV dyes.
195
+ */
196
+ export class PaletteService {
197
+ /**
198
+ * Create a new PaletteService
199
+ * @param options - Optional configuration including logger
200
+ */
201
+ constructor(options = {}) {
202
+ this.logger = options.logger ?? NoOpLogger;
203
+ }
204
+ /**
205
+ * Sample pixels from an array if it exceeds maxSamples
206
+ * Uses uniform sampling to maintain color distribution
207
+ * CORE-PERF-004: Fixed potential out-of-bounds access on last iteration
208
+ */
209
+ samplePixels(pixels, maxSamples) {
210
+ if (pixels.length <= maxSamples) {
211
+ return pixels;
212
+ }
213
+ const step = pixels.length / maxSamples;
214
+ const samples = [];
215
+ for (let i = 0; i < maxSamples; i++) {
216
+ // Clamp index to prevent out-of-bounds access due to floating-point rounding
217
+ const index = Math.min(Math.floor(i * step), pixels.length - 1);
218
+ samples.push(pixels[index]);
219
+ }
220
+ return samples;
221
+ }
222
+ /**
223
+ * Extract dominant colors from pixel data
224
+ *
225
+ * @param pixels - Array of RGB pixel values
226
+ * @param options - Extraction options (colorCount, maxIterations, etc.)
227
+ * @returns Array of extracted colors sorted by dominance (most dominant first)
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const pixels = [{ r: 255, g: 0, b: 0 }, { r: 254, g: 1, b: 1 }, ...];
232
+ * const palette = paletteService.extractPalette(pixels, { colorCount: 4 });
233
+ * // Returns: [{ color: { r: 255, g: 0, b: 0 }, dominance: 45, pixelCount: 4500 }, ...]
234
+ * ```
235
+ */
236
+ extractPalette(pixels, options = {}) {
237
+ const opts = { ...PaletteService.DEFAULT_OPTIONS, ...options };
238
+ // Validate colorCount
239
+ const colorCount = Math.max(1, Math.min(10, opts.colorCount));
240
+ // SECURITY: Clamp maxIterations to prevent DoS via algorithmic complexity
241
+ const maxIterations = Math.max(1, Math.min(100, opts.maxIterations));
242
+ if (pixels.length === 0) {
243
+ this.logger.warn('PaletteService.extractPalette: Empty pixel array');
244
+ return [];
245
+ }
246
+ this.logger.info(`Extracting ${colorCount} colors from ${pixels.length} pixels`);
247
+ // Sample pixels if too many
248
+ const sampledPixels = this.samplePixels(pixels, opts.maxSamples);
249
+ // Run K-means clustering
250
+ const { centroids, clusterSizes } = kMeansClustering(sampledPixels, colorCount, maxIterations, opts.convergenceThreshold);
251
+ // Calculate total pixels for dominance percentage
252
+ const totalPixels = clusterSizes.reduce((sum, size) => sum + size, 0);
253
+ // Build result array
254
+ const result = centroids.map((color, i) => ({
255
+ color,
256
+ dominance: totalPixels > 0 ? Math.round((clusterSizes[i] / totalPixels) * 100) : 0,
257
+ pixelCount: clusterSizes[i],
258
+ }));
259
+ // Sort by dominance (most dominant first)
260
+ result.sort((a, b) => b.dominance - a.dominance);
261
+ this.logger.info(`Extracted colors: ${result.map((r) => `${r.dominance}%`).join(', ')}`);
262
+ return result;
263
+ }
264
+ /**
265
+ * Extract colors from pixel data and match each to the closest FFXIV dye
266
+ *
267
+ * @param pixels - Array of RGB pixel values
268
+ * @param dyeService - DyeService instance for matching
269
+ * @param options - Extraction options
270
+ * @returns Array of palette matches sorted by dominance
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * const matches = paletteService.extractAndMatchPalette(pixels, dyeService, { colorCount: 4 });
275
+ * // Returns: [{ extracted: {...}, matchedDye: {...}, distance: 12.3, dominance: 45 }, ...]
276
+ * ```
277
+ */
278
+ extractAndMatchPalette(pixels, dyeService, options = {}) {
279
+ // Extract palette
280
+ const extracted = this.extractPalette(pixels, options);
281
+ // Match each extracted color to closest dye
282
+ const matches = [];
283
+ for (const ex of extracted) {
284
+ // Convert RGB to hex for DyeService
285
+ const hex = ColorService.rgbToHex(ex.color.r, ex.color.g, ex.color.b);
286
+ const matchedDye = dyeService.findClosestDye(hex);
287
+ if (matchedDye) {
288
+ // Calculate distance between extracted and matched colors
289
+ const distance = rgbDistance(ex.color, matchedDye.rgb);
290
+ matches.push({
291
+ extracted: ex.color,
292
+ matchedDye,
293
+ distance,
294
+ dominance: ex.dominance,
295
+ });
296
+ }
297
+ }
298
+ return matches;
299
+ }
300
+ /**
301
+ * Convert flat pixel array (Uint8ClampedArray from canvas) to RGB array
302
+ * Skips alpha channel
303
+ *
304
+ * @param data - Flat array of RGBA values [r, g, b, a, r, g, b, a, ...]
305
+ * @returns Array of RGB objects
306
+ */
307
+ static pixelDataToRGB(data) {
308
+ const pixels = [];
309
+ for (let i = 0; i < data.length; i += 4) {
310
+ pixels.push({
311
+ r: data[i],
312
+ g: data[i + 1],
313
+ b: data[i + 2],
314
+ // Skip alpha at data[i + 3]
315
+ });
316
+ }
317
+ return pixels;
318
+ }
319
+ /**
320
+ * Filter out near-transparent pixels from RGBA data
321
+ * Useful for images with transparent backgrounds
322
+ *
323
+ * @param data - Flat array of RGBA values
324
+ * @param alphaThreshold - Minimum alpha to include (0-255, default: 128)
325
+ * @returns Array of RGB objects for non-transparent pixels
326
+ */
327
+ static pixelDataToRGBFiltered(data, alphaThreshold = 128) {
328
+ const pixels = [];
329
+ for (let i = 0; i < data.length; i += 4) {
330
+ const alpha = data[i + 3];
331
+ if (alpha >= alphaThreshold) {
332
+ pixels.push({
333
+ r: data[i],
334
+ g: data[i + 1],
335
+ b: data[i + 2],
336
+ });
337
+ }
338
+ }
339
+ return pixels;
340
+ }
341
+ }
342
+ /** Default extraction options */
343
+ PaletteService.DEFAULT_OPTIONS = {
344
+ colorCount: 4,
345
+ maxIterations: 25,
346
+ convergenceThreshold: 1.0,
347
+ maxSamples: 10000,
348
+ };
349
+ //# sourceMappingURL=PaletteService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaletteService.js","sourceRoot":"","sources":["../../src/services/PaletteService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * @xivdyetools/core - Preset Service
3
+ *
4
+ * Manages preset color palettes for FFXIV glamours.
5
+ * Provides themed color combinations for jobs, seasons, events, and aesthetics.
6
+ *
7
+ * @module services/PresetService
8
+ * @example
9
+ * ```typescript
10
+ * import { PresetService, presetData, DyeService, dyeDatabase } from '@xivdyetools/core';
11
+ *
12
+ * const presetService = new PresetService(presetData);
13
+ * const dyeService = new DyeService(dyeDatabase);
14
+ *
15
+ * // Get all job presets
16
+ * const jobPresets = presetService.getPresetsByCategory('jobs');
17
+ *
18
+ * // Get a preset with resolved dye objects
19
+ * const rdmPreset = presetService.getPresetWithDyes('job-rdm', dyeService);
20
+ * ```
21
+ */
22
+ import type { PresetData, PresetPalette, PresetCategory, CategoryMeta, ResolvedPreset, Dye } from '../types/index.js';
23
+ /**
24
+ * Interface for DyeService to resolve dye IDs to Dye objects
25
+ * Using interface to avoid circular dependency
26
+ */
27
+ interface IDyeService {
28
+ getDyeById(id: number): Dye | null;
29
+ }
30
+ /**
31
+ * Service for managing preset color palettes
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const presetService = new PresetService(presetData);
36
+ *
37
+ * // List categories
38
+ * const categories = presetService.getCategories();
39
+ *
40
+ * // Get presets by category
41
+ * const jobPresets = presetService.getPresetsByCategory('jobs');
42
+ *
43
+ * // Search presets
44
+ * const results = presetService.searchPresets('red');
45
+ * ```
46
+ */
47
+ export declare class PresetService {
48
+ private data;
49
+ private presetById;
50
+ /**
51
+ * Initialize the preset service with preset data
52
+ * @param presetData - Preset data object (import from presets.json)
53
+ */
54
+ constructor(presetData: PresetData);
55
+ /**
56
+ * Get all preset categories with metadata
57
+ * @returns Array of category metadata with IDs
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const categories = presetService.getCategories();
62
+ * // [{ id: 'jobs', name: 'FFXIV Jobs', description: '...', icon: '⚔️' }, ...]
63
+ * ```
64
+ */
65
+ getCategories(): (CategoryMeta & {
66
+ id: string;
67
+ })[];
68
+ /**
69
+ * Get metadata for a specific category
70
+ * @param category - Category identifier
71
+ * @returns Category metadata or undefined if not found
72
+ */
73
+ getCategoryMeta(category: PresetCategory): CategoryMeta | undefined;
74
+ /**
75
+ * Get all presets
76
+ * @returns Array of all preset palettes
77
+ */
78
+ getAllPresets(): PresetPalette[];
79
+ /**
80
+ * Get all presets in a specific category
81
+ * @param category - Category to filter by
82
+ * @returns Array of presets in that category
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const jobPresets = presetService.getPresetsByCategory('jobs');
87
+ * // Returns all job-themed presets (RDM, BLM, WHM, etc.)
88
+ * ```
89
+ */
90
+ getPresetsByCategory(category: PresetCategory): PresetPalette[];
91
+ /**
92
+ * Get a specific preset by ID
93
+ * @param id - Preset identifier (e.g., "job-rdm")
94
+ * @returns Preset or undefined if not found
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const rdm = presetService.getPreset('job-rdm');
99
+ * if (rdm) {
100
+ * console.log(rdm.name); // "Red Mage"
101
+ * console.log(rdm.dyes); // [5738, 13115, 13117, 5729]
102
+ * }
103
+ * ```
104
+ */
105
+ getPreset(id: string): PresetPalette | undefined;
106
+ /**
107
+ * Get preset count by category
108
+ * @returns Map of category to preset count
109
+ */
110
+ getPresetCountByCategory(): Map<PresetCategory, number>;
111
+ /**
112
+ * Search presets by name or tags
113
+ * @param query - Search query (case-insensitive)
114
+ * @returns Array of matching presets
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * // Search by name
119
+ * const results = presetService.searchPresets('red');
120
+ * // Returns: Red Mage, Blood Red themed presets, etc.
121
+ *
122
+ * // Search by tag
123
+ * const tankResults = presetService.searchPresets('tank');
124
+ * // Returns: Paladin, Warrior, Dark Knight, Gunbreaker
125
+ * ```
126
+ */
127
+ searchPresets(query: string): PresetPalette[];
128
+ /**
129
+ * Search presets by tag (exact match)
130
+ * @param tag - Tag to search for (case-insensitive)
131
+ * @returns Array of presets with that tag
132
+ */
133
+ getPresetsByTag(tag: string): PresetPalette[];
134
+ /**
135
+ * Get a random preset, optionally filtered by category
136
+ * @param category - Optional category to filter by
137
+ * @returns Random preset, or undefined if no presets exist
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * // Random from all presets
142
+ * const random = presetService.getRandomPreset();
143
+ *
144
+ * // Random job preset
145
+ * const randomJob = presetService.getRandomPreset('jobs');
146
+ * ```
147
+ */
148
+ getRandomPreset(category?: PresetCategory): PresetPalette | undefined;
149
+ /**
150
+ * Get preset with resolved Dye objects
151
+ * Requires a DyeService instance to resolve dye IDs to full Dye objects
152
+ *
153
+ * @param id - Preset identifier
154
+ * @param dyeService - DyeService instance for resolving dye IDs
155
+ * @returns Resolved preset with full Dye objects, or undefined if preset not found
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const dyeService = new DyeService(dyeDatabase);
160
+ * const resolved = presetService.getPresetWithDyes('job-rdm', dyeService);
161
+ *
162
+ * if (resolved) {
163
+ * resolved.resolvedDyes.forEach(dye => {
164
+ * if (dye) {
165
+ * console.log(`${dye.name}: ${dye.hex}`);
166
+ * }
167
+ * });
168
+ * }
169
+ * ```
170
+ */
171
+ getPresetWithDyes(id: string, dyeService: IDyeService): ResolvedPreset | undefined;
172
+ /**
173
+ * Resolve multiple presets with their Dye objects
174
+ * @param presets - Array of presets to resolve
175
+ * @param dyeService - DyeService instance for resolving dye IDs
176
+ * @returns Array of resolved presets
177
+ */
178
+ resolvePresets(presets: PresetPalette[], dyeService: IDyeService): ResolvedPreset[];
179
+ /**
180
+ * Get data version
181
+ * @returns Version string from preset data
182
+ */
183
+ getVersion(): string;
184
+ /**
185
+ * Get last update timestamp
186
+ * @returns ISO date string of last update
187
+ */
188
+ getLastUpdated(): string;
189
+ /**
190
+ * Get total number of presets
191
+ * @returns Total preset count
192
+ */
193
+ getPresetCount(): number;
194
+ }
195
+ export {};
196
+ //# sourceMappingURL=PresetService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PresetService.d.ts","sourceRoot":"","sources":["../../src/services/PresetService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAc,EACd,GAAG,EACJ,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,UAAU,WAAW;IACnB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,UAAU,CAA6B;IAE/C;;;OAGG;gBACS,UAAU,EAAE,UAAU;IAUlC;;;;;;;;;OASG;IACH,aAAa,IAAI,CAAC,YAAY,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE;IAOlD;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,GAAG,SAAS;IAQnE;;;OAGG;IACH,aAAa,IAAI,aAAa,EAAE;IAIhC;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,aAAa,EAAE;IAI/D;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIhD;;;OAGG;IACH,wBAAwB,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC;IAYvD;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IAc7C;;;;OAIG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE;IAS7C;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS;IAcrE;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS;IAYlF;;;;;OAKG;IACH,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,EAAE;IAWnF;;;OAGG;IACH,UAAU,IAAI,MAAM;IAIpB;;;OAGG;IACH,cAAc,IAAI,MAAM;IAIxB;;;OAGG;IACH,cAAc,IAAI,MAAM;CAGzB"}