apexify.js 4.6.2 → 4.7.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 (129) hide show
  1. package/dist/cjs/ai/ApexModules.d.ts.map +1 -1
  2. package/dist/cjs/ai/ApexModules.js +56 -7
  3. package/dist/cjs/ai/ApexModules.js.map +1 -1
  4. package/dist/cjs/ai/functions/readFiles.js +1 -1
  5. package/dist/cjs/ai/functions/readFiles.js.map +1 -1
  6. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
  7. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js +2 -1
  8. package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
  9. package/dist/cjs/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
  10. package/dist/cjs/ai/modals-chat/electronHub/speechModels.js +1 -1
  11. package/dist/cjs/ai/modals-chat/electronHub/speechModels.js.map +1 -1
  12. package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
  13. package/dist/cjs/canvas/ApexPainter.js +27 -28
  14. package/dist/cjs/canvas/ApexPainter.js.map +1 -1
  15. package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts +11 -0
  16. package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
  17. package/dist/cjs/canvas/Themes/Level-Up/levelup.js +163 -0
  18. package/dist/cjs/canvas/Themes/Level-Up/levelup.js.map +1 -0
  19. package/dist/cjs/canvas/utils/Background/bg.d.ts +17 -10
  20. package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -1
  21. package/dist/cjs/canvas/utils/Background/bg.js +102 -27
  22. package/dist/cjs/canvas/utils/Background/bg.js.map +1 -1
  23. package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -1
  24. package/dist/cjs/canvas/utils/Custom/customLines.js +43 -19
  25. package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -1
  26. package/dist/cjs/canvas/utils/General/general functions.d.ts +6 -1
  27. package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -1
  28. package/dist/cjs/canvas/utils/General/general functions.js +19 -20
  29. package/dist/cjs/canvas/utils/General/general functions.js.map +1 -1
  30. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +3 -9
  31. package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  32. package/dist/cjs/canvas/utils/Image/imageProperties.js +220 -214
  33. package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -1
  34. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts +12 -14
  35. package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -1
  36. package/dist/cjs/canvas/utils/Texts/textProperties.js +100 -91
  37. package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -1
  38. package/dist/cjs/canvas/utils/types.d.ts +89 -109
  39. package/dist/cjs/canvas/utils/types.d.ts.map +1 -1
  40. package/dist/cjs/canvas/utils/types.js.map +1 -1
  41. package/dist/cjs/canvas/utils/utils.d.ts +2 -4
  42. package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
  43. package/dist/cjs/canvas/utils/utils.js +2 -5
  44. package/dist/cjs/canvas/utils/utils.js.map +1 -1
  45. package/dist/cjs/index.d.ts.map +1 -1
  46. package/dist/cjs/index.js +31 -3
  47. package/dist/cjs/index.js.map +1 -1
  48. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  49. package/dist/esm/ai/ApexModules.d.ts.map +1 -1
  50. package/dist/esm/ai/ApexModules.js +56 -7
  51. package/dist/esm/ai/ApexModules.js.map +1 -1
  52. package/dist/esm/ai/functions/readFiles.js +1 -1
  53. package/dist/esm/ai/functions/readFiles.js.map +1 -1
  54. package/dist/esm/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
  55. package/dist/esm/ai/modals-chat/electronHub/chatmodels.js +2 -1
  56. package/dist/esm/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
  57. package/dist/esm/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
  58. package/dist/esm/ai/modals-chat/electronHub/speechModels.js +1 -1
  59. package/dist/esm/ai/modals-chat/electronHub/speechModels.js.map +1 -1
  60. package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
  61. package/dist/esm/canvas/ApexPainter.js +27 -28
  62. package/dist/esm/canvas/ApexPainter.js.map +1 -1
  63. package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts +11 -0
  64. package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
  65. package/dist/esm/canvas/Themes/Level-Up/levelup.js +163 -0
  66. package/dist/esm/canvas/Themes/Level-Up/levelup.js.map +1 -0
  67. package/dist/esm/canvas/utils/Background/bg.d.ts +17 -10
  68. package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -1
  69. package/dist/esm/canvas/utils/Background/bg.js +102 -27
  70. package/dist/esm/canvas/utils/Background/bg.js.map +1 -1
  71. package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -1
  72. package/dist/esm/canvas/utils/Custom/customLines.js +43 -19
  73. package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -1
  74. package/dist/esm/canvas/utils/General/general functions.d.ts +6 -1
  75. package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -1
  76. package/dist/esm/canvas/utils/General/general functions.js +19 -20
  77. package/dist/esm/canvas/utils/General/general functions.js.map +1 -1
  78. package/dist/esm/canvas/utils/Image/imageProperties.d.ts +3 -9
  79. package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -1
  80. package/dist/esm/canvas/utils/Image/imageProperties.js +220 -214
  81. package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -1
  82. package/dist/esm/canvas/utils/Texts/textProperties.d.ts +12 -14
  83. package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -1
  84. package/dist/esm/canvas/utils/Texts/textProperties.js +100 -91
  85. package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -1
  86. package/dist/esm/canvas/utils/types.d.ts +89 -109
  87. package/dist/esm/canvas/utils/types.d.ts.map +1 -1
  88. package/dist/esm/canvas/utils/types.js.map +1 -1
  89. package/dist/esm/canvas/utils/utils.d.ts +2 -4
  90. package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
  91. package/dist/esm/canvas/utils/utils.js +2 -5
  92. package/dist/esm/canvas/utils/utils.js.map +1 -1
  93. package/dist/esm/index.d.ts.map +1 -1
  94. package/dist/esm/index.js +31 -3
  95. package/dist/esm/index.js.map +1 -1
  96. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  97. package/lib/ai/ApexModules.ts +83 -11
  98. package/lib/ai/functions/readFiles.ts +1 -1
  99. package/lib/ai/modals-chat/electronHub/chatmodels.ts +4 -2
  100. package/lib/ai/modals-chat/electronHub/speechModels.ts +2 -1
  101. package/lib/canvas/ApexPainter.ts +52 -61
  102. package/lib/canvas/Themes/Level-Up/levelup.ts +183 -0
  103. package/lib/canvas/utils/Background/bg.ts +179 -65
  104. package/lib/canvas/utils/Custom/customLines.ts +53 -20
  105. package/lib/canvas/utils/General/general functions.ts +21 -29
  106. package/lib/canvas/utils/Image/imageProperties.ts +399 -318
  107. package/lib/canvas/utils/Texts/textProperties.ts +213 -162
  108. package/lib/canvas/utils/types.ts +74 -107
  109. package/lib/canvas/utils/utils.ts +2 -5
  110. package/lib/index.ts +38 -10
  111. package/package.json +3 -2
  112. package/dist/cjs/canvas/utils/Background/circular.d.ts +0 -3
  113. package/dist/cjs/canvas/utils/Background/circular.d.ts.map +0 -1
  114. package/dist/cjs/canvas/utils/Background/circular.js +0 -13
  115. package/dist/cjs/canvas/utils/Background/circular.js.map +0 -1
  116. package/dist/cjs/canvas/utils/Background/radius.d.ts +0 -18
  117. package/dist/cjs/canvas/utils/Background/radius.d.ts.map +0 -1
  118. package/dist/cjs/canvas/utils/Background/radius.js +0 -104
  119. package/dist/cjs/canvas/utils/Background/radius.js.map +0 -1
  120. package/dist/esm/canvas/utils/Background/circular.d.ts +0 -3
  121. package/dist/esm/canvas/utils/Background/circular.d.ts.map +0 -1
  122. package/dist/esm/canvas/utils/Background/circular.js +0 -13
  123. package/dist/esm/canvas/utils/Background/circular.js.map +0 -1
  124. package/dist/esm/canvas/utils/Background/radius.d.ts +0 -18
  125. package/dist/esm/canvas/utils/Background/radius.d.ts.map +0 -1
  126. package/dist/esm/canvas/utils/Background/radius.js +0 -104
  127. package/dist/esm/canvas/utils/Background/radius.js.map +0 -1
  128. package/lib/canvas/utils/Background/circular.ts +0 -17
  129. package/lib/canvas/utils/Background/radius.ts +0 -102
@@ -1,97 +1,211 @@
1
1
  import { loadImage, SKRSContext2D } from "@napi-rs/canvas";
2
- import { CanvasConfig } from '../types';
3
- import path from 'path';
2
+ import { CanvasConfig } from "../types";
3
+ import path from "path";
4
4
 
5
+ interface ZoomConfig {
6
+ scale?: number;
7
+ x?: number;
8
+ y?: number;
9
+ }
5
10
 
6
11
  /**
7
- * Draws a gradient background on the canvas.
8
- * No zoom logic is applied.
12
+ * Draws a gradient background on the canvas with optional zoom support.
9
13
  * @param ctx The canvas rendering context.
10
14
  * @param canvas The canvas configuration object.
15
+ * @param zoom Optional zoom configuration.
11
16
  */
12
- export async function drawBackgroundGradient(ctx: SKRSContext2D, canvas: CanvasConfig): Promise<void> {
17
+ export async function drawBackgroundGradient(
18
+ ctx: SKRSContext2D,
19
+ canvas: CanvasConfig,
20
+ zoom?: ZoomConfig,
21
+ blur?: number
22
+ ): Promise<void> {
13
23
  if (canvas.gradientBg) {
14
- const {
15
- type,
16
- startX = 0,
17
- startY = 0,
18
- endX = canvas.width || 500,
19
- endY = canvas.height || 500,
20
- startRadius = 0,
21
- endRadius = 0,
22
- colors
23
- } = canvas.gradientBg;
24
-
25
- if (!colors || colors.length === 0) {
26
- throw new Error('You need to provide colors for the gradient.');
27
- }
28
-
29
- let gradient;
30
- if (type === 'linear' || type === undefined) {
31
- gradient = ctx.createLinearGradient(startX, startY, endX, endY);
32
- } else if (type === 'radial') {
33
- gradient = ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);
34
- } else {
35
- throw new Error('Unsupported gradient type.');
36
- }
37
-
38
- for (const { stop, color } of colors) {
39
- gradient.addColorStop(stop as number, color as string);
24
+ const {
25
+ type,
26
+ startX = 0,
27
+ startY = 0,
28
+ endX = canvas.width || 500,
29
+ endY = canvas.height || 500,
30
+ startRadius = 0,
31
+ endRadius = 0,
32
+ colors
33
+ } = canvas.gradientBg;
34
+
35
+ if (!colors || colors.length === 0) {
36
+ throw new Error("You need to provide colors for the gradient.");
37
+ }
38
+
39
+ let gradient;
40
+ if (type === "linear" || type === undefined) {
41
+ let finalStartX = startX, finalStartY = startY, finalEndX = endX, finalEndY = endY;
42
+
43
+ if (zoom) {
44
+ const scale = Math.max(1, zoom.scale || 1);
45
+ finalStartX = (zoom.x || 0) - (endX - startX) / (2 * scale);
46
+ finalStartY = (zoom.y || 0) - (endY - startY) / (2 * scale);
47
+ finalEndX = (zoom.x || 0) + (endX - startX) / (2 * scale);
48
+ finalEndY = (zoom.y || 0) + (endY - startY) / (2 * scale);
49
+ }
50
+
51
+ gradient = ctx.createLinearGradient(finalStartX, finalStartY, finalEndX, finalEndY);
52
+ } else if (type === "radial") {
53
+ gradient = ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);
54
+ } else {
55
+ throw new Error("Unsupported gradient type.");
56
+ }
57
+
58
+ for (const { stop, color } of colors) {
59
+ gradient.addColorStop(stop as number, color as string);
60
+ }
61
+
62
+ if (blur) {
63
+ ctx.filter = `blur(${blur}px)`;
40
64
  }
41
-
42
- const canvasWidth = canvas.width || 500;
43
- const canvasHeight = canvas.height || 500;
65
+
44
66
  ctx.fillStyle = gradient;
45
- ctx.fillRect(0, 0, canvasWidth, canvasHeight);
67
+ ctx.fillRect(0, 0, canvas.width || 500, canvas.height || 500);
68
+
69
+ ctx.filter = "none";
46
70
  }
47
71
  }
48
-
72
+
49
73
  /**
50
- * Draws a solid background color on the canvas.
51
- * No zoom logic is applied.
74
+ * Draws a solid background color on the canvas with optional zoom effect.
52
75
  * @param ctx The canvas rendering context.
53
76
  * @param canvas The canvas configuration object.
77
+ * @param zoom Optional zoom configuration.
54
78
  */
55
- export async function drawBackgroundColor(ctx: SKRSContext2D, canvas: CanvasConfig): Promise<void> {
79
+ export async function drawBackgroundColor(
80
+ ctx: SKRSContext2D,
81
+ canvas: CanvasConfig,
82
+ zoom?: ZoomConfig,
83
+ blur?: number
84
+ ): Promise<void> {
56
85
  const canvasWidth = canvas.width || 500;
57
86
  const canvasHeight = canvas.height || 500;
58
-
59
- // Fill the entire area starting at (0,0) (assuming translation is handled elsewhere)
60
- if (canvas.colorBg !== 'transparent') {
61
- ctx.fillStyle = canvas.colorBg as string;
62
- ctx.fillRect(0, 0, canvasWidth, canvasHeight);
87
+
88
+ ctx.save();
89
+
90
+
91
+ if (blur) {
92
+ ctx.filter = `blur(${blur}px)`;
93
+ }
94
+
95
+ if (zoom) {
96
+ const scale = Math.max(1, zoom.scale || 1);
97
+ const zoomedWidth = canvasWidth / scale;
98
+ const zoomedHeight = canvasHeight / scale;
99
+
100
+ ctx.scale(scale, scale);
101
+ ctx.translate((zoom.x || 0) + zoomedWidth / 2, (zoom.y || 0) + zoomedHeight / 2);
63
102
  }
103
+
104
+ if (canvas.colorBg !== "transparent") {
105
+ ctx.fillStyle = canvas.colorBg as string;
106
+ ctx.fillRect(0, 0, canvasWidth, canvasHeight);
107
+ }
108
+
109
+ ctx.filter = "none";
110
+ ctx.restore();
64
111
  }
65
112
 
66
113
  /**
67
- * Draws a custom background image on the canvas.
68
- * No zoom logic is applied.
114
+ * Draws a custom background image on the canvas with optional zoom functionality.
69
115
  * @param ctx The canvas rendering context.
70
116
  * @param canvas The canvas configuration object.
117
+ * @param zoom Optional zoom configuration.
71
118
  */
72
- export async function customBackground(ctx: SKRSContext2D, canvas: CanvasConfig): Promise<void> {
119
+ export async function customBackground(
120
+ ctx: SKRSContext2D,
121
+ canvas: CanvasConfig,
122
+ zoom?: ZoomConfig,
123
+ blur?: number
124
+ ): Promise<void> {
73
125
  if (canvas.customBg) {
74
- try {
75
- let imageBuffer: string;
76
-
77
- if (canvas.customBg.startsWith('http')) {
78
- imageBuffer = canvas.customBg;
79
- } else {
80
- imageBuffer = path.join(process.cwd(), canvas.customBg);
126
+ try {
127
+ let imageBuffer: string;
128
+
129
+ if (canvas.customBg.startsWith("http")) {
130
+ imageBuffer = canvas.customBg;
131
+ } else {
132
+ imageBuffer = path.join(process.cwd(), canvas.customBg);
133
+ }
134
+
135
+ const image = await loadImage(imageBuffer);
136
+ const imgWidth = image.width;
137
+ const imgHeight = image.height;
138
+ const canvasWidth = canvas.width || imgWidth;
139
+ const canvasHeight = canvas.height || imgHeight;
140
+
141
+ if (blur) {
142
+ ctx.filter = `blur(${blur}px)`;
143
+ }
144
+
145
+ if (zoom) {
146
+ const scale = Math.max(1, zoom.scale || 1);
147
+ const cropWidth = imgWidth / scale;
148
+ const cropHeight = imgHeight / scale;
149
+
150
+ let sx = (zoom.x || 0) - cropWidth / 2;
151
+ let sy = (zoom.y || 0) - cropHeight / 2;
152
+
153
+ sx = Math.max(0, Math.min(sx, imgWidth - cropWidth));
154
+ sy = Math.max(0, Math.min(sy, imgHeight - cropHeight));
155
+
156
+ ctx.drawImage(image, sx, sy, cropWidth, cropHeight, 0, 0, canvasWidth, canvasHeight);
157
+ } else {
158
+ ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
159
+ }
160
+ ctx.filter = "none";
161
+ } catch (error: any) {
162
+ console.error("Error loading custom background image:", error.message);
81
163
  }
164
+ }
165
+ }
166
+
167
+ export function backgroundRadius(
168
+ ctx: SKRSContext2D,
169
+ x: number,
170
+ y: number,
171
+ width: number,
172
+ height: number,
173
+ borderRadius: number | "circular",
174
+ borderPosition: string = "all"
175
+ ): void {
176
+ ctx.beginPath();
82
177
 
83
- const image = await loadImage(imageBuffer);
178
+ if (borderRadius === "circular") {
179
+ const circleRadius = Math.min(width, height) / 2;
180
+ ctx.arc(x + width / 2, y + height / 2, circleRadius, 0, 2 * Math.PI);
181
+ } else if (typeof borderRadius === "number" && borderRadius > 0) {
182
+ const br: number = Math.min(borderRadius, width / 2, height / 2);
183
+ const selectedPositions = new Set(borderPosition.toLowerCase().split(",").map((s) => s.trim()));
84
184
 
85
- // Use canvas dimensions without additional x/y translation,
86
- // because createCanvas already translated the context.
87
- const canvasWidth = canvas.width || image.width;
88
- const canvasHeight = canvas.height || image.height;
185
+ const roundTopLeft = selectedPositions.has("all") || selectedPositions.has("top-left") || (selectedPositions.has("top") && selectedPositions.has("left"));
186
+ const roundTopRight = selectedPositions.has("all") || selectedPositions.has("top-right") || (selectedPositions.has("top") && selectedPositions.has("right"));
187
+ const roundBottomRight = selectedPositions.has("all") || selectedPositions.has("bottom-right") || (selectedPositions.has("bottom") && selectedPositions.has("right"));
188
+ const roundBottomLeft = selectedPositions.has("all") || selectedPositions.has("bottom-left") || (selectedPositions.has("bottom") && selectedPositions.has("left"));
89
189
 
90
- // Draw the image so that it fills the canvas area relative to (0,0)
91
- ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
190
+ const tl = roundTopLeft ? br : 0;
191
+ const tr = roundTopRight ? br : 0;
192
+ const brR = roundBottomRight ? br : 0;
193
+ const bl = roundBottomLeft ? br : 0;
92
194
 
93
- } catch (error: any) {
94
- console.error('Error loading custom background image:', error.message);
95
- }
195
+ ctx.moveTo(x + tl, y);
196
+ ctx.lineTo(x + width - tr, y);
197
+ if (tr > 0) ctx.arc(x + width - tr, y + tr, tr, -Math.PI / 2, 0, false);
198
+ ctx.lineTo(x + width, y + height - brR);
199
+ if (brR > 0) ctx.arc(x + width - brR, y + height - brR, brR, 0, Math.PI / 2, false);
200
+ ctx.lineTo(x + bl, y + height);
201
+ if (bl > 0) ctx.arc(x + bl, y + height - bl, bl, Math.PI / 2, Math.PI, false);
202
+ ctx.lineTo(x, y + tl);
203
+ if (tl > 0) ctx.arc(x + tl, y + tl, tl, Math.PI, -Math.PI / 2, false);
204
+ } else {
205
+ ctx.rect(x, y, width, height);
96
206
  }
97
- }
207
+
208
+ ctx.closePath();
209
+ ctx.clip();
210
+ }
211
+
@@ -1,3 +1,4 @@
1
+ import { createGradient } from "../Image/imageProperties";
1
2
  import { CustomOptions } from "../types";
2
3
 
3
4
  export function customLines(ctx: any, options: CustomOptions[]) {
@@ -19,7 +20,7 @@ export function customLines(ctx: any, options: CustomOptions[]) {
19
20
 
20
21
  if (!isSingleLine && inSingleLineSequence) {
21
22
  ctx.stroke();
22
- applyAdditionalStroke(ctx, currentStyle);
23
+ applyStroke(ctx, currentStyle, startCoordinates, endCoordinates);
23
24
  inSingleLineSequence = false;
24
25
  currentStyle = null;
25
26
  }
@@ -37,7 +38,13 @@ export function customLines(ctx: any, options: CustomOptions[]) {
37
38
 
38
39
  const appliedStyle = inSingleLineSequence ? currentStyle : lineStyle;
39
40
  ctx.lineWidth = appliedStyle?.width || 1;
40
- ctx.strokeStyle = appliedStyle?.color || 'black';
41
+
42
+ if (appliedStyle?.gradient) {
43
+ ctx.strokeStyle = createGradient(ctx, appliedStyle.gradient, start.x, start.y, endCoordinates.x, endCoordinates.y);
44
+ } else {
45
+ ctx.strokeStyle = appliedStyle?.color || 'black';
46
+ }
47
+
41
48
  ctx.lineJoin = appliedStyle?.lineJoin || 'miter';
42
49
  ctx.lineCap = appliedStyle?.lineCap || 'butt';
43
50
 
@@ -48,31 +55,36 @@ export function customLines(ctx: any, options: CustomOptions[]) {
48
55
  ctx.setLineDash([]);
49
56
  }
50
57
 
51
- if (typeof appliedStyle?.lineRadius === 'number') {
52
- const borderRadius = appliedStyle.lineRadius;
58
+ if (typeof appliedStyle?.lineRadius === 'number' && appliedStyle.lineRadius > 0) {
59
+ const radius = appliedStyle.lineRadius;
53
60
  const dx = endCoordinates.x - start.x;
54
61
  const dy = endCoordinates.y - start.y;
55
62
  const angle = Math.atan2(dy, dx);
56
- const offsetX = Math.cos(angle) * borderRadius;
57
- const offsetY = Math.sin(angle) * borderRadius;
58
- ctx.moveTo(start.x + offsetX, start.y + offsetY);
59
- ctx.lineTo(endCoordinates.x - offsetX, endCoordinates.y - offsetY);
60
- } else if (appliedStyle?.lineRadius === 'circular') {
63
+
64
+ ctx.lineCap = "round";
65
+ ctx.stroke();
66
+
67
+ ctx.beginPath();
68
+ ctx.arc(start.x, start.y, radius, angle + Math.PI / 2, angle - Math.PI / 2, true);
69
+ ctx.arc(endCoordinates.x, endCoordinates.y, radius, angle - Math.PI / 2, angle + Math.PI / 2, false);
70
+ ctx.fill();
71
+ }
72
+
73
+ else if (appliedStyle?.lineRadius === 'circular') {
61
74
  const dx = endCoordinates.x - start.x;
62
75
  const dy = endCoordinates.y - start.y;
63
76
  const length = Math.sqrt(dx * dx + dy * dy);
64
- const angle = Math.atan2(dy, dx);
65
- const halfWidth = appliedStyle.width ? appliedStyle.width / 2 : 1;
66
- ctx.moveTo(start.x + Math.cos(angle - Math.PI / 2) * halfWidth, start.y + Math.sin(angle - Math.PI / 2) * halfWidth);
67
- ctx.arc(start.x, start.y, length / 2, angle - Math.PI / 2, angle + Math.PI / 2);
68
- ctx.lineTo(endCoordinates.x + Math.cos(angle + Math.PI / 2) * halfWidth, endCoordinates.y + Math.sin(angle + Math.PI / 2) * halfWidth);
69
- ctx.arc(endCoordinates.x, endCoordinates.y, length / 2, angle + Math.PI / 2, angle - Math.PI / 2, true);
77
+
78
+ ctx.beginPath();
79
+ ctx.arcTo(start.x, start.y, endCoordinates.x, endCoordinates.y, length / 2);
80
+ ctx.arcTo(endCoordinates.x, endCoordinates.y, start.x, start.y, length / 2);
70
81
  ctx.closePath();
82
+ ctx.stroke();
71
83
  }
72
84
 
73
85
  if (!inSingleLineSequence || i === options.length - 1) {
74
86
  ctx.stroke();
75
- applyAdditionalStroke(ctx, appliedStyle);
87
+ applyStroke(ctx, appliedStyle, startCoordinates, endCoordinates);
76
88
  }
77
89
 
78
90
  previousEndCoordinates = endCoordinates;
@@ -84,11 +96,32 @@ export function customLines(ctx: any, options: CustomOptions[]) {
84
96
  }
85
97
  }
86
98
 
87
- function applyAdditionalStroke(ctx: any, style: any) {
99
+ function applyStroke(ctx: any, style: any, start: any, end: any) {
88
100
  if (style.stroke) {
89
- const { color, width } = style.stroke;
90
- ctx.strokeStyle = color || 'black';
91
- ctx.lineWidth = width || 1;
101
+ const { color, width, gradient, lineRadius, lineCap } = style.stroke;
102
+ const prevStrokeStyle = ctx.strokeStyle;
103
+ const prevLineWidth = ctx.lineWidth;
104
+ const prevLineCap = ctx.lineCap;
105
+
106
+ if (gradient) {
107
+ ctx.strokeStyle = createGradient(ctx, gradient, start.x, start.y, end.x, end.y);
108
+ } else {
109
+ ctx.strokeStyle = color || prevStrokeStyle;
110
+ }
111
+
112
+ ctx.lineWidth = width || prevLineWidth;
113
+ ctx.lineCap = lineCap || prevLineCap;
92
114
  ctx.stroke();
115
+
116
+ if (typeof lineRadius === 'number' && lineRadius > 0) {
117
+ ctx.beginPath();
118
+ ctx.arc(start.x, start.y, lineRadius, 0, Math.PI * 2);
119
+ ctx.arc(end.x, end.y, lineRadius, 0, Math.PI * 2);
120
+ ctx.fill();
121
+ }
122
+
123
+ ctx.strokeStyle = prevStrokeStyle;
124
+ ctx.lineWidth = prevLineWidth;
125
+ ctx.lineCap = prevLineCap;
93
126
  }
94
127
  }
@@ -31,7 +31,6 @@ export async function loadImages(imagePath: string) {
31
31
 
32
32
  /**
33
33
  * Resizes an image using Sharp with additional options for quality, kernel, and withoutEnlargement.
34
- *
35
34
  * @param resizeOptions - The options for resizing.
36
35
  * @returns A Promise that resolves with the resized image as a Buffer.
37
36
  */
@@ -41,14 +40,8 @@ export async function resizingImg(resizeOptions: ResizeOptions): Promise<Buffer>
41
40
  throw new Error("Image path is required for resizing.");
42
41
  }
43
42
 
44
- let absoluteImagePath: string;
45
- if (resizeOptions.imagePath.startsWith("http")) {
46
- absoluteImagePath = resizeOptions.imagePath;
47
- } else {
48
- absoluteImagePath = path.join(process.cwd(), resizeOptions.imagePath);
49
- }
50
-
51
- const image = sharp(absoluteImagePath);
43
+ // Use `loadImages()` instead of handling the fetch manually
44
+ const image = await loadImages(resizeOptions.imagePath);
52
45
 
53
46
  const resizeOptionsForSharp: sharp.ResizeOptions = {
54
47
  width: resizeOptions.size?.width || 500,
@@ -60,21 +53,18 @@ export async function resizingImg(resizeOptions: ResizeOptions): Promise<Buffer>
60
53
 
61
54
  const quality = resizeOptions.quality ?? 90;
62
55
 
63
- const resizedBuffer: Buffer = await image
56
+ const resizedBuffer: Buffer = await image
64
57
  .resize(resizeOptionsForSharp)
65
58
  .png({ quality })
66
59
  .toBuffer();
67
-
68
60
 
69
61
  return resizedBuffer;
70
-
71
62
  } catch (error) {
72
63
  console.error("Error resizing image:", error);
73
64
  throw new Error("Failed to resize image");
74
65
  }
75
66
  }
76
67
 
77
-
78
68
  export async function converter(imagePath: string, newExtension: string) {
79
69
  try {
80
70
  const validExtensions: (keyof sharp.FormatEnum)[] = ['jpeg', 'png', 'webp', 'tiff', 'gif', 'avif', 'heif', 'raw', 'pdf', 'svg'];
@@ -382,53 +372,55 @@ export async function cropOuter(options: cropOptions): Promise<Buffer> {
382
372
  }
383
373
 
384
374
 
375
+ /**
376
+ * Detects dominant colors from an image.
377
+ *
378
+ * @param imagePath - Local path or URL of the image.
379
+ * @returns A sorted array of dominant colors with their frequency.
380
+ */
385
381
  export async function detectColors(imagePath: string): Promise<{ color: string; frequency: string }[]> {
386
382
  try {
387
383
  let image: any;
384
+
388
385
  if (imagePath.startsWith('http')) {
389
386
  const response = await fetch(imagePath);
390
- if (!response.ok) {
391
- throw new Error("Failed to fetch image.");
392
- }
387
+ if (!response.ok) throw new Error(`Failed to fetch image: ${response.statusText}`);
393
388
  const buffer = await response.arrayBuffer();
394
389
  image = await loadImage(Buffer.from(buffer));
395
390
  } else {
396
- const localImagePath = path.join(process.cwd(), imagePath);
391
+ const localImagePath = path.resolve(imagePath);
397
392
  image = await loadImage(localImagePath);
398
393
  }
399
394
 
400
395
  const canvas = createCanvas(image.width, image.height);
401
- const ctx = canvas.getContext('2d') as any;
402
-
396
+ const ctx = canvas.getContext('2d');
403
397
  ctx.drawImage(image, 0, 0, image.width, image.height);
404
398
 
405
399
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
406
400
  const data = imageData.data;
407
401
 
408
402
  const colorFrequency: { [color: string]: number } = {};
409
-
410
403
  for (let i = 0; i < data.length; i += 4) {
411
- const red = data[i];
412
- const green = data[i + 1];
413
- const blue = data[i + 2];
414
-
415
- const color = `${red},${green},${blue}`;
404
+ const [r, g, b, a] = [data[i], data[i + 1], data[i + 2], data[i + 3]];
405
+ if (a < 50) continue;
416
406
 
407
+ const color = `${r},${g},${b}`;
417
408
  colorFrequency[color] = (colorFrequency[color] || 0) + 1;
418
409
  }
419
410
 
420
411
  const totalPixels = canvas.width * canvas.height;
421
412
 
422
413
  const dominantColors = Object.entries(colorFrequency)
423
- .filter(([color, frequency]: [string, number]) => (frequency / totalPixels) * 100 >= 2)
424
- .map(([color, frequency]: [string, number]) => ({
414
+ .map(([color, frequency]) => ({
425
415
  color,
426
416
  frequency: ((frequency / totalPixels) * 100).toFixed(2),
427
- }));
417
+ }))
418
+ .filter(colorObj => parseFloat(colorObj.frequency) >= 0.1)
419
+ .sort((a, b) => parseFloat(b.frequency) - parseFloat(a.frequency));
428
420
 
429
421
  return dominantColors;
430
422
  } catch (error) {
431
- console.error('Error:', error);
423
+ console.error("❌ Error detecting colors:", error);
432
424
  return [];
433
425
  }
434
426
  }