@xivdyetools/svg 1.0.0

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 (50) hide show
  1. package/README.md +136 -0
  2. package/dist/accessibility-comparison.d.ts +66 -0
  3. package/dist/accessibility-comparison.d.ts.map +1 -0
  4. package/dist/accessibility-comparison.js +201 -0
  5. package/dist/accessibility-comparison.js.map +1 -0
  6. package/dist/base.d.ts +115 -0
  7. package/dist/base.d.ts.map +1 -0
  8. package/dist/base.js +201 -0
  9. package/dist/base.js.map +1 -0
  10. package/dist/budget-comparison.d.ts +121 -0
  11. package/dist/budget-comparison.d.ts.map +1 -0
  12. package/dist/budget-comparison.js +331 -0
  13. package/dist/budget-comparison.js.map +1 -0
  14. package/dist/comparison-grid.d.ts +61 -0
  15. package/dist/comparison-grid.d.ts.map +1 -0
  16. package/dist/comparison-grid.js +366 -0
  17. package/dist/comparison-grid.js.map +1 -0
  18. package/dist/contrast-matrix.d.ts +78 -0
  19. package/dist/contrast-matrix.d.ts.map +1 -0
  20. package/dist/contrast-matrix.js +303 -0
  21. package/dist/contrast-matrix.js.map +1 -0
  22. package/dist/dye-info-card.d.ts +34 -0
  23. package/dist/dye-info-card.d.ts.map +1 -0
  24. package/dist/dye-info-card.js +218 -0
  25. package/dist/dye-info-card.js.map +1 -0
  26. package/dist/gradient.d.ts +49 -0
  27. package/dist/gradient.d.ts.map +1 -0
  28. package/dist/gradient.js +131 -0
  29. package/dist/gradient.js.map +1 -0
  30. package/dist/harmony-wheel.d.ts +38 -0
  31. package/dist/harmony-wheel.d.ts.map +1 -0
  32. package/dist/harmony-wheel.js +158 -0
  33. package/dist/harmony-wheel.js.map +1 -0
  34. package/dist/index.d.ts +31 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +32 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/palette-grid.d.ts +105 -0
  39. package/dist/palette-grid.d.ts.map +1 -0
  40. package/dist/palette-grid.js +277 -0
  41. package/dist/palette-grid.js.map +1 -0
  42. package/dist/preset-swatch.d.ts +76 -0
  43. package/dist/preset-swatch.d.ts.map +1 -0
  44. package/dist/preset-swatch.js +226 -0
  45. package/dist/preset-swatch.js.map +1 -0
  46. package/dist/random-dyes-grid.d.ts +45 -0
  47. package/dist/random-dyes-grid.d.ts.map +1 -0
  48. package/dist/random-dyes-grid.js +143 -0
  49. package/dist/random-dyes-grid.js.map +1 -0
  50. package/package.json +56 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Gradient Bar SVG Generator
3
+ *
4
+ * Generates a color gradient visualization showing steps between two colors
5
+ * with hex codes and matched dye names below each step.
6
+ */
7
+ import { createSvgDocument, rect, line, text, getContrastTextColor, THEME, FONTS, } from './base.js';
8
+ /**
9
+ * Generates a gradient bar SVG showing color progression with dye matches
10
+ */
11
+ export function generateGradientBar(options) {
12
+ const { steps, width = 800, height = 200, showTicks = true, showEndLabels = true, startLabel = 'START', endLabel = 'END', } = options;
13
+ if (steps.length < 2) {
14
+ throw new Error('Gradient requires at least 2 steps');
15
+ }
16
+ const elements = [];
17
+ // Layout constants
18
+ const padding = 20;
19
+ const barHeight = 60;
20
+ const barY = 40;
21
+ const hexLabelY = barY + barHeight + 20;
22
+ const nameLabelY = hexLabelY + 18;
23
+ const endLabelY = barY - 10;
24
+ const barWidth = width - padding * 2;
25
+ const stepWidth = barWidth / steps.length;
26
+ // Background
27
+ elements.push(rect(0, 0, width, height, THEME.background, { rx: 12 }));
28
+ // Draw each color step
29
+ steps.forEach((step, i) => {
30
+ const x = padding + i * stepWidth;
31
+ // Color rectangle
32
+ elements.push(rect(x, barY, stepWidth, barHeight, step.hex, {
33
+ stroke: i === 0 || i === steps.length - 1 ? '#ffffff' : undefined,
34
+ strokeWidth: i === 0 || i === steps.length - 1 ? 2 : undefined,
35
+ }));
36
+ // Hex label below the bar
37
+ const centerX = x + stepWidth / 2;
38
+ elements.push(text(centerX, hexLabelY, step.hex.toUpperCase(), {
39
+ fill: THEME.textMuted,
40
+ fontSize: 11,
41
+ fontFamily: FONTS.mono,
42
+ textAnchor: 'middle',
43
+ }));
44
+ // Dye name below hex (if available)
45
+ // Uses primaryCjk font for CJK language support (Japanese/Korean/Chinese dye names)
46
+ if (step.dyeName) {
47
+ const truncatedName = truncateName(step.dyeName, 12);
48
+ elements.push(text(centerX, nameLabelY, truncatedName, {
49
+ fill: THEME.text,
50
+ fontSize: 10,
51
+ fontFamily: FONTS.primaryCjk,
52
+ textAnchor: 'middle',
53
+ }));
54
+ }
55
+ });
56
+ // Draw tick marks between steps
57
+ if (showTicks) {
58
+ for (let i = 1; i < steps.length; i++) {
59
+ const tickX = padding + i * stepWidth;
60
+ elements.push(line(tickX, barY - 5, tickX, barY, THEME.textDim, 1));
61
+ elements.push(line(tickX, barY + barHeight, tickX, barY + barHeight + 5, THEME.textDim, 1));
62
+ }
63
+ }
64
+ // Draw START/END labels (localized)
65
+ // Uses primaryCjk font for CJK language support (e.g., 開始/終了 in Japanese)
66
+ if (showEndLabels) {
67
+ elements.push(text(padding + stepWidth / 2, endLabelY, startLabel, {
68
+ fill: THEME.textMuted,
69
+ fontSize: 10,
70
+ fontFamily: FONTS.primaryCjk,
71
+ textAnchor: 'middle',
72
+ fontWeight: 'bold',
73
+ }));
74
+ elements.push(text(padding + (steps.length - 0.5) * stepWidth, endLabelY, endLabel, {
75
+ fill: THEME.textMuted,
76
+ fontSize: 10,
77
+ fontFamily: FONTS.primaryCjk,
78
+ textAnchor: 'middle',
79
+ fontWeight: 'bold',
80
+ }));
81
+ }
82
+ // Outer border around the gradient bar
83
+ elements.push(rect(padding, barY, barWidth, barHeight, 'none', {
84
+ stroke: THEME.border,
85
+ strokeWidth: 1,
86
+ }));
87
+ return createSvgDocument(width, height, elements.join('\n'));
88
+ }
89
+ /**
90
+ * Truncates a name to fit within the step width
91
+ */
92
+ function truncateName(name, maxLength) {
93
+ if (name.length <= maxLength)
94
+ return name;
95
+ return name.slice(0, maxLength - 2) + '..';
96
+ }
97
+ /**
98
+ * Interpolates between two colors in RGB space
99
+ * @param color1 Starting hex color
100
+ * @param color2 Ending hex color
101
+ * @param ratio Interpolation ratio (0 = color1, 1 = color2)
102
+ */
103
+ export function interpolateColor(color1, color2, ratio) {
104
+ const hex1 = color1.replace('#', '');
105
+ const hex2 = color2.replace('#', '');
106
+ const r1 = parseInt(hex1.slice(0, 2), 16);
107
+ const g1 = parseInt(hex1.slice(2, 4), 16);
108
+ const b1 = parseInt(hex1.slice(4, 6), 16);
109
+ const r2 = parseInt(hex2.slice(0, 2), 16);
110
+ const g2 = parseInt(hex2.slice(2, 4), 16);
111
+ const b2 = parseInt(hex2.slice(4, 6), 16);
112
+ const r = Math.round(r1 + (r2 - r1) * ratio);
113
+ const g = Math.round(g1 + (g2 - g1) * ratio);
114
+ const b = Math.round(b1 + (b2 - b1) * ratio);
115
+ return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
116
+ }
117
+ /**
118
+ * Generates an array of interpolated colors between start and end
119
+ * @param startColor Starting hex color
120
+ * @param endColor Ending hex color
121
+ * @param stepCount Number of steps (including start and end)
122
+ */
123
+ export function generateGradientColors(startColor, endColor, stepCount) {
124
+ const colors = [];
125
+ for (let i = 0; i < stepCount; i++) {
126
+ const ratio = i / (stepCount - 1);
127
+ colors.push(interpolateColor(startColor, endColor, ratio));
128
+ }
129
+ return colors;
130
+ }
131
+ //# sourceMappingURL=gradient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradient.js","sourceRoot":"","sources":["../src/gradient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Harmony Wheel SVG Generator (v4 Style)
3
+ *
4
+ * Generates a modern color harmony wheel visualization matching the v4 web app design.
5
+ * Features:
6
+ * - Large center swatch showing the base color with glow effect
7
+ * - Smooth conic gradient ring for the color spectrum
8
+ * - Small colored dot nodes positioned on the ring
9
+ * - Dashed connection lines between harmony points
10
+ *
11
+ * Colors are positioned on the wheel based on their HSV hue value,
12
+ * matching the traditional color wheel representation.
13
+ */
14
+ export interface HarmonyDye {
15
+ id: number;
16
+ name: string;
17
+ hex: string;
18
+ category?: string;
19
+ }
20
+ export interface HarmonyWheelOptions {
21
+ /** Base color hex */
22
+ baseColor: string;
23
+ /** Name of the base color/dye */
24
+ baseName?: string;
25
+ /** Type of harmony (triadic, complementary, etc.) */
26
+ harmonyType: string;
27
+ /** Matched dyes for the harmony */
28
+ dyes: HarmonyDye[];
29
+ /** Width of the output image */
30
+ width?: number;
31
+ /** Height of the output image */
32
+ height?: number;
33
+ }
34
+ /**
35
+ * Generates a v4-style harmony wheel SVG
36
+ */
37
+ export declare function generateHarmonyWheel(options: HarmonyWheelOptions): string;
38
+ //# sourceMappingURL=harmony-wheel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harmony-wheel.d.ts","sourceRoot":"","sources":["../src/harmony-wheel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAuCD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAkGzE"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Harmony Wheel SVG Generator (v4 Style)
3
+ *
4
+ * Generates a modern color harmony wheel visualization matching the v4 web app design.
5
+ * Features:
6
+ * - Large center swatch showing the base color with glow effect
7
+ * - Smooth conic gradient ring for the color spectrum
8
+ * - Small colored dot nodes positioned on the ring
9
+ * - Dashed connection lines between harmony points
10
+ *
11
+ * Colors are positioned on the wheel based on their HSV hue value,
12
+ * matching the traditional color wheel representation.
13
+ */
14
+ import { createSvgDocument, rect, hexToRgb, THEME, } from './base.js';
15
+ /**
16
+ * Converts RGB to HSV and returns the hue (0-360)
17
+ */
18
+ function rgbToHue(r, g, b) {
19
+ r /= 255;
20
+ g /= 255;
21
+ b /= 255;
22
+ const max = Math.max(r, g, b);
23
+ const min = Math.min(r, g, b);
24
+ const delta = max - min;
25
+ let hue = 0;
26
+ if (delta === 0) {
27
+ hue = 0; // Achromatic (gray)
28
+ }
29
+ else if (max === r) {
30
+ hue = 60 * (((g - b) / delta) % 6);
31
+ }
32
+ else if (max === g) {
33
+ hue = 60 * ((b - r) / delta + 2);
34
+ }
35
+ else {
36
+ hue = 60 * ((r - g) / delta + 4);
37
+ }
38
+ if (hue < 0)
39
+ hue += 360;
40
+ return hue;
41
+ }
42
+ /**
43
+ * Gets the hue angle from a hex color
44
+ */
45
+ function getHueFromHex(hex) {
46
+ const { r, g, b } = hexToRgb(hex);
47
+ return rgbToHue(r, g, b);
48
+ }
49
+ /**
50
+ * Generates a v4-style harmony wheel SVG
51
+ */
52
+ export function generateHarmonyWheel(options) {
53
+ const { baseColor, baseName, harmonyType, dyes, width = 400, height = 400, } = options;
54
+ const centerX = width / 2;
55
+ const centerY = height / 2;
56
+ const wheelRadius = Math.min(width, height) / 2 - 30;
57
+ // v4 style sizing
58
+ const innerRadiusRatio = 0.6; // Thinner ring
59
+ const nodeRadiusRatio = 0.8; // Where nodes sit on the ring
60
+ const centerSwatchRadius = wheelRadius * 0.4; // Large center swatch (v4 style: 120px equivalent)
61
+ const harmonyNodeRadius = 10; // Small nodes (v4 style: 14px)
62
+ const baseNodeRadius = 12; // Slightly larger for base (v4 style: 18px)
63
+ const elements = [];
64
+ // Background with rounded corners
65
+ elements.push(rect(0, 0, width, height, THEME.background, { rx: 16 }));
66
+ // Generate defs for glow filter and drop shadow
67
+ elements.push(`<defs>
68
+ <filter id="centerGlow" x="-50%" y="-50%" width="200%" height="200%">
69
+ <feGaussianBlur in="SourceGraphic" stdDeviation="20" result="blur"/>
70
+ <feColorMatrix in="blur" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.4 0"/>
71
+ <feMerge>
72
+ <feMergeNode/>
73
+ <feMergeNode in="SourceGraphic"/>
74
+ </feMerge>
75
+ </filter>
76
+ <filter id="nodeShadow" x="-50%" y="-50%" width="200%" height="200%">
77
+ <feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.5"/>
78
+ </filter>
79
+ </defs>`);
80
+ // Color wheel ring (v4 style: smoother gradient with reduced opacity)
81
+ elements.push(generateColorWheelRing(centerX, centerY, wheelRadius, innerRadiusRatio));
82
+ // Get base color hue for positioning
83
+ const baseHue = getHueFromHex(baseColor);
84
+ // Calculate positions for all nodes
85
+ const baseAngle = baseHue - 90; // -90 to start from top
86
+ const baseRad = (baseAngle * Math.PI) / 180;
87
+ const baseX = centerX + Math.cos(baseRad) * wheelRadius * nodeRadiusRatio;
88
+ const baseY = centerY + Math.sin(baseRad) * wheelRadius * nodeRadiusRatio;
89
+ // Draw dashed connection lines (v4 style)
90
+ // Line from center to base node
91
+ elements.push(createDashedLine(centerX, centerY, baseX, baseY, 'rgba(255, 255, 255, 0.4)', 1.5));
92
+ // Lines to harmony nodes
93
+ dyes.forEach((dye) => {
94
+ const dyeHue = getHueFromHex(dye.hex);
95
+ const dyeAngle = dyeHue - 90;
96
+ const dyeRad = (dyeAngle * Math.PI) / 180;
97
+ const dyeX = centerX + Math.cos(dyeRad) * wheelRadius * nodeRadiusRatio;
98
+ const dyeY = centerY + Math.sin(dyeRad) * wheelRadius * nodeRadiusRatio;
99
+ elements.push(createDashedLine(centerX, centerY, dyeX, dyeY, 'rgba(255, 255, 255, 0.4)', 1.5));
100
+ });
101
+ // Center swatch with glow effect (v4 style: prominent center display)
102
+ // Glow layer
103
+ elements.push(`<circle cx="${centerX}" cy="${centerY}" r="${centerSwatchRadius}" fill="${baseColor}" filter="url(#centerGlow)"/>`);
104
+ // Main center circle with border
105
+ elements.push(`<circle cx="${centerX}" cy="${centerY}" r="${centerSwatchRadius}" fill="${baseColor}" stroke="${THEME.background}" stroke-width="4"/>`);
106
+ // Draw harmony dye nodes (small colored dots)
107
+ dyes.forEach((dye) => {
108
+ const dyeHue = getHueFromHex(dye.hex);
109
+ const dyeAngle = dyeHue - 90;
110
+ const dyeRad = (dyeAngle * Math.PI) / 180;
111
+ const dyeX = centerX + Math.cos(dyeRad) * wheelRadius * nodeRadiusRatio;
112
+ const dyeY = centerY + Math.sin(dyeRad) * wheelRadius * nodeRadiusRatio;
113
+ // Small colored node with white border
114
+ elements.push(`<circle cx="${dyeX}" cy="${dyeY}" r="${harmonyNodeRadius}" fill="${dye.hex}" stroke="#ffffff" stroke-width="2" filter="url(#nodeShadow)"/>`);
115
+ });
116
+ // Draw base color node (slightly larger)
117
+ elements.push(`<circle cx="${baseX}" cy="${baseY}" r="${baseNodeRadius}" fill="${baseColor}" stroke="#ffffff" stroke-width="3" filter="url(#nodeShadow)"/>`);
118
+ return createSvgDocument(width, height, elements.join('\n'));
119
+ }
120
+ /**
121
+ * Creates a dashed line SVG element
122
+ */
123
+ function createDashedLine(x1, y1, x2, y2, color, strokeWidth) {
124
+ return `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="${color}" stroke-width="${strokeWidth}" stroke-dasharray="6,4"/>`;
125
+ }
126
+ /**
127
+ * Generates a smooth color wheel ring (v4 style with reduced opacity)
128
+ */
129
+ function generateColorWheelRing(cx, cy, radius, innerRadiusRatio = 0.6) {
130
+ const segments = [];
131
+ const segmentCount = 90; // More segments for smoother gradient
132
+ const segmentAngle = 360 / segmentCount;
133
+ const innerRadius = radius * innerRadiusRatio;
134
+ for (let i = 0; i < segmentCount; i++) {
135
+ const startAngle = i * segmentAngle;
136
+ const endAngle = startAngle + segmentAngle + 0.5; // Slight overlap to prevent gaps
137
+ const hue = startAngle;
138
+ // Calculate arc points
139
+ const startRad = ((startAngle - 90) * Math.PI) / 180;
140
+ const endRad = ((endAngle - 90) * Math.PI) / 180;
141
+ // Outer arc points
142
+ const ox1 = cx + radius * Math.cos(startRad);
143
+ const oy1 = cy + radius * Math.sin(startRad);
144
+ const ox2 = cx + radius * Math.cos(endRad);
145
+ const oy2 = cy + radius * Math.sin(endRad);
146
+ // Inner arc points
147
+ const ix1 = cx + innerRadius * Math.cos(startRad);
148
+ const iy1 = cy + innerRadius * Math.sin(startRad);
149
+ const ix2 = cx + innerRadius * Math.cos(endRad);
150
+ const iy2 = cy + innerRadius * Math.sin(endRad);
151
+ // Create wedge path
152
+ const path = `M ${ix1} ${iy1} L ${ox1} ${oy1} A ${radius} ${radius} 0 0 1 ${ox2} ${oy2} L ${ix2} ${iy2} A ${innerRadius} ${innerRadius} 0 0 0 ${ix1} ${iy1} Z`;
153
+ // v4 style: slightly reduced saturation (85%) and opacity (0.8) for softer look
154
+ segments.push(`<path d="${path}" fill="hsl(${hue}, 85%, 50%)" opacity="0.8" stroke="none"/>`);
155
+ }
156
+ return segments.join('\n');
157
+ }
158
+ //# sourceMappingURL=harmony-wheel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harmony-wheel.js","sourceRoot":"","sources":["../src/harmony-wheel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @xivdyetools/svg
3
+ *
4
+ * SVG card generators for XIV Dye Tools.
5
+ * All functions are pure: data in → SVG string out.
6
+ * Rendering to PNG (via resvg-wasm, etc.) is handled by each consuming app.
7
+ *
8
+ * @module svg
9
+ */
10
+ export { escapeXml, hexToRgb, rgbToHex, getLuminance, getContrastTextColor, createSvgDocument, rect, circle, line, text, arcPath, group, THEME, FONTS, } from './base.js';
11
+ export { generateHarmonyWheel } from './harmony-wheel.js';
12
+ export type { HarmonyDye, HarmonyWheelOptions } from './harmony-wheel.js';
13
+ export { generateGradientBar, interpolateColor, generateGradientColors, } from './gradient.js';
14
+ export type { GradientStep, GradientBarOptions } from './gradient.js';
15
+ export { generatePaletteGrid, getMatchQuality, MATCH_QUALITIES, } from './palette-grid.js';
16
+ export type { PaletteEntry, PaletteGridOptions, PaletteGridLabels, MatchQuality, } from './palette-grid.js';
17
+ export { generateAccessibilityComparison, generateCompactAccessibilityRow, } from './accessibility-comparison.js';
18
+ export type { AccessibilityComparisonOptions, VisionType, AllVisionTypes, } from './accessibility-comparison.js';
19
+ export { generateContrastMatrix, calculateContrast } from './contrast-matrix.js';
20
+ export type { ContrastDye, ContrastMatrixOptions, ContrastResult, WCAGLevel, } from './contrast-matrix.js';
21
+ export { generateRandomDyesGrid } from './random-dyes-grid.js';
22
+ export type { RandomDyeInfo, RandomDyesGridOptions } from './random-dyes-grid.js';
23
+ export { generateComparisonGrid } from './comparison-grid.js';
24
+ export type { ComparisonGridOptions } from './comparison-grid.js';
25
+ export { generateDyeInfoCard } from './dye-info-card.js';
26
+ export type { DyeInfoCardOptions } from './dye-info-card.js';
27
+ export { generatePresetSwatch, generateCompactPresetSwatch, CATEGORY_DISPLAY, } from './preset-swatch.js';
28
+ export type { PresetSwatchOptions } from './preset-swatch.js';
29
+ export { generateBudgetComparison, generateNoWorldSetSvg, generateErrorSvg, formatGil, } from './budget-comparison.js';
30
+ export type { DyePriceData, BudgetSuggestion, BudgetSortOption, BudgetSvgLabels, BudgetComparisonOptions, } from './budget-comparison.js';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,KAAK,EACL,KAAK,EACL,KAAK,GACN,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG1E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGtE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,8BAA8B,EAC9B,UAAU,EACV,cAAc,GACf,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EACV,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,SAAS,GACV,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGlF,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,GACV,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,uBAAuB,GACxB,MAAM,wBAAwB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @xivdyetools/svg
3
+ *
4
+ * SVG card generators for XIV Dye Tools.
5
+ * All functions are pure: data in → SVG string out.
6
+ * Rendering to PNG (via resvg-wasm, etc.) is handled by each consuming app.
7
+ *
8
+ * @module svg
9
+ */
10
+ // Base utilities & primitives
11
+ export { escapeXml, hexToRgb, rgbToHex, getLuminance, getContrastTextColor, createSvgDocument, rect, circle, line, text, arcPath, group, THEME, FONTS, } from './base.js';
12
+ // Harmony Wheel
13
+ export { generateHarmonyWheel } from './harmony-wheel.js';
14
+ // Gradient Bar
15
+ export { generateGradientBar, interpolateColor, generateGradientColors, } from './gradient.js';
16
+ // Palette Grid (color extraction match results)
17
+ export { generatePaletteGrid, getMatchQuality, MATCH_QUALITIES, } from './palette-grid.js';
18
+ // Accessibility / Colorblind Comparison
19
+ export { generateAccessibilityComparison, generateCompactAccessibilityRow, } from './accessibility-comparison.js';
20
+ // WCAG Contrast Matrix
21
+ export { generateContrastMatrix, calculateContrast } from './contrast-matrix.js';
22
+ // Random Dyes Grid
23
+ export { generateRandomDyesGrid } from './random-dyes-grid.js';
24
+ // Dye Comparison Grid
25
+ export { generateComparisonGrid } from './comparison-grid.js';
26
+ // Dye Info Card
27
+ export { generateDyeInfoCard } from './dye-info-card.js';
28
+ // Preset Swatch
29
+ export { generatePresetSwatch, generateCompactPresetSwatch, CATEGORY_DISPLAY, } from './preset-swatch.js';
30
+ // Budget Comparison
31
+ export { generateBudgetComparison, generateNoWorldSetSvg, generateErrorSvg, formatGil, } from './budget-comparison.js';
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,8BAA8B;AAC9B,OAAO,EACL,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,KAAK,EACL,KAAK,EACL,KAAK,GACN,MAAM,WAAW,CAAC;AAEnB,gBAAgB;AAChB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG1D,eAAe;AACf,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAGvB,gDAAgD;AAChD,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAQ3B,wCAAwC;AACxC,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,GAChC,MAAM,+BAA+B,CAAC;AAOvC,uBAAuB;AACvB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAQjF,mBAAmB;AACnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,sBAAsB;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,gBAAgB;AAChB,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzD,gBAAgB;AAChB,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,oBAAoB;AACpB,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,GACV,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Palette Grid SVG Generator
3
+ *
4
+ * Generates a visual comparison of extracted colors to matched FFXIV dyes.
5
+ * Used by the /extractor image command to display color extraction results.
6
+ *
7
+ * Layout:
8
+ * +----------------------------------------------------------+
9
+ * | [Extracted Color] 42% --> [Matched Dye] Dalamud Red |
10
+ * | #B01515 #AA1111 Δ8.5 [EXCELLENT] |
11
+ * +----------------------------------------------------------+
12
+ *
13
+ * @module svg/palette-grid
14
+ */
15
+ import type { RGB, Dye } from '@xivdyetools/core';
16
+ export interface MatchQuality {
17
+ /** Locale key for translation lookup (e.g., 'perfect', 'excellent') */
18
+ key: string;
19
+ /** Human-readable label */
20
+ label: string;
21
+ /** Short label for display */
22
+ shortLabel: string;
23
+ /** Distance threshold for this quality level */
24
+ maxDistance: number;
25
+ }
26
+ /**
27
+ * Match quality thresholds
28
+ *
29
+ * Based on Euclidean distance in RGB space:
30
+ * - Max possible distance: ~441 (black to white)
31
+ * - Noticeable difference: ~10-15
32
+ * - Perceptually similar: ~25-30
33
+ */
34
+ export declare const MATCH_QUALITIES: MatchQuality[];
35
+ /**
36
+ * Get the quality rating for a color distance
37
+ */
38
+ export declare function getMatchQuality(distance: number): MatchQuality;
39
+ /**
40
+ * A single palette entry with extracted and matched colors
41
+ */
42
+ export interface PaletteEntry {
43
+ /** The extracted RGB color from the image */
44
+ extracted: RGB;
45
+ /** The closest matching FFXIV dye */
46
+ matchedDye: Dye;
47
+ /** Color distance (Euclidean in RGB space) */
48
+ distance: number;
49
+ /** Percentage of pixels with this color (0-100) */
50
+ dominance: number;
51
+ }
52
+ /**
53
+ * Translatable labels for the palette grid SVG.
54
+ * Pass these from the bot's i18n system to localize the image.
55
+ */
56
+ export interface PaletteGridLabels {
57
+ /** Label above extracted color (e.g., "EXTRACTED") */
58
+ extracted: string;
59
+ /** Label above matched dye (e.g., "MATCHED DYE") */
60
+ matchedDye: string;
61
+ /** Suffix for dominance percentage (e.g., "of image") */
62
+ ofImage: string;
63
+ /** Empty state message (e.g., "No colors extracted from image") */
64
+ noColors: string;
65
+ /** Quality badge labels keyed by quality key */
66
+ quality: Record<string, string>;
67
+ }
68
+ /**
69
+ * Options for generating the palette grid
70
+ */
71
+ export interface PaletteGridOptions {
72
+ /** Array of palette entries to display */
73
+ entries: PaletteEntry[];
74
+ /** Canvas width in pixels (default: 800) */
75
+ width?: number;
76
+ /** Show color distance values (default: true) */
77
+ showDistance?: boolean;
78
+ /** Title text (optional) */
79
+ title?: string;
80
+ /** Translated labels for i18n (defaults to English if omitted) */
81
+ labels?: PaletteGridLabels;
82
+ }
83
+ /**
84
+ * Generate a palette grid SVG showing extracted colors matched to dyes
85
+ *
86
+ * @param options - Palette grid configuration
87
+ * @returns SVG string
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const svg = generatePaletteGrid({
92
+ * entries: [
93
+ * {
94
+ * extracted: { r: 176, g: 21, b: 21 },
95
+ * matchedDye: { name: 'Dalamud Red', hex: '#AA1111', ... },
96
+ * distance: 8.5,
97
+ * dominance: 42,
98
+ * },
99
+ * ],
100
+ * });
101
+ * const png = await renderSvgToPng(svg);
102
+ * ```
103
+ */
104
+ export declare function generatePaletteGrid(options: PaletteGridOptions): string;
105
+ //# sourceMappingURL=palette-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette-grid.d.ts","sourceRoot":"","sources":["../src/palette-grid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAgBlD,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,EAMzC,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAO9D;AAMD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,SAAS,EAAE,GAAG,CAAC;IACf,qCAAqC;IACrC,UAAU,EAAE,GAAG,CAAC;IAChB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAkCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA2DvE"}