hyperprop-charting-library 0.1.17 → 0.1.18
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/hyperprop-charting-library.cjs +67 -26
- package/dist/hyperprop-charting-library.d.ts +1 -4
- package/dist/hyperprop-charting-library.js +67 -26
- package/dist/index.cjs +67 -26
- package/dist/index.d.cts +1 -4
- package/dist/index.d.ts +1 -4
- package/dist/index.js +67 -26
- package/docs/API.md +6 -7
- package/docs/RECIPES.md +2 -3
- package/package.json +1 -1
|
@@ -53,15 +53,12 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
53
53
|
labelBorderWidth: 1,
|
|
54
54
|
labelBorderStyle: "solid",
|
|
55
55
|
showPriceActionButton: false,
|
|
56
|
+
priceActionButtonIcon: "plusThin",
|
|
56
57
|
priceActionButtonText: "+",
|
|
57
|
-
priceActionButtonSize:
|
|
58
|
-
priceActionButtonGap:
|
|
59
|
-
priceActionButtonBackgroundColor: "#1f2937",
|
|
60
|
-
priceActionButtonTextColor: "#e2e8f0",
|
|
61
|
-
priceActionButtonBorderColor: "#475569",
|
|
62
|
-
priceActionButtonBorderWidth: 1,
|
|
58
|
+
priceActionButtonSize: 16,
|
|
59
|
+
priceActionButtonGap: 4,
|
|
63
60
|
priceActionButtonRounded: true,
|
|
64
|
-
priceActionButtonBorderRadius:
|
|
61
|
+
priceActionButtonBorderRadius: 8
|
|
65
62
|
};
|
|
66
63
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
67
64
|
visible: false,
|
|
@@ -1151,35 +1148,79 @@ function createChart(element, options = {}) {
|
|
|
1151
1148
|
strokeCrosshairLabel(priceX, priceY, priceWidth);
|
|
1152
1149
|
drawText(priceText, priceX + labelPaddingX, priceY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1153
1150
|
if (crosshair.showPriceActionButton) {
|
|
1154
|
-
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12,
|
|
1151
|
+
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12, Math.max(12, labelHeight - 4));
|
|
1155
1152
|
const buttonGap = Math.max(0, Math.round(crosshair.priceActionButtonGap));
|
|
1156
|
-
const
|
|
1153
|
+
const containerPaddingX = 5;
|
|
1154
|
+
const containerWidth = buttonSize + containerPaddingX * 2;
|
|
1155
|
+
const containerX = priceX - buttonGap - containerWidth;
|
|
1156
|
+
const containerY = priceY;
|
|
1157
|
+
const buttonX = containerX + containerPaddingX;
|
|
1157
1158
|
const buttonY = priceY + (labelHeight - buttonSize) / 2;
|
|
1158
1159
|
const buttonRadius = crosshair.priceActionButtonRounded ? clamp(Math.round(crosshair.priceActionButtonBorderRadius), 0, buttonSize / 2) : 0;
|
|
1159
|
-
const buttonBorderWidth = Math.max(
|
|
1160
|
-
|
|
1161
|
-
|
|
1160
|
+
const buttonBorderWidth = Math.max(1, Math.round(labelBorderWidth || 1));
|
|
1161
|
+
const buttonCenterX = buttonX + buttonSize / 2;
|
|
1162
|
+
const buttonCenterY = buttonY + buttonSize / 2;
|
|
1163
|
+
const containerRadius = labelRadius;
|
|
1164
|
+
ctx.fillStyle = labelBackground;
|
|
1165
|
+
fillRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1166
|
+
if (labelBorderWidth > 0) {
|
|
1167
|
+
ctx.save();
|
|
1168
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1169
|
+
ctx.lineWidth = labelBorderWidth;
|
|
1170
|
+
ctx.setLineDash([]);
|
|
1171
|
+
strokeRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1172
|
+
ctx.restore();
|
|
1173
|
+
}
|
|
1162
1174
|
if (buttonBorderWidth > 0) {
|
|
1163
1175
|
ctx.save();
|
|
1164
|
-
ctx.strokeStyle =
|
|
1176
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1165
1177
|
ctx.lineWidth = buttonBorderWidth;
|
|
1166
1178
|
ctx.setLineDash([]);
|
|
1167
|
-
|
|
1179
|
+
if (crosshair.priceActionButtonRounded) {
|
|
1180
|
+
ctx.beginPath();
|
|
1181
|
+
ctx.arc(
|
|
1182
|
+
buttonCenterX,
|
|
1183
|
+
buttonCenterY,
|
|
1184
|
+
Math.max(1, buttonSize / 2 - buttonBorderWidth / 2),
|
|
1185
|
+
0,
|
|
1186
|
+
Math.PI * 2
|
|
1187
|
+
);
|
|
1188
|
+
ctx.stroke();
|
|
1189
|
+
} else {
|
|
1190
|
+
strokeRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, buttonRadius);
|
|
1191
|
+
}
|
|
1192
|
+
ctx.restore();
|
|
1193
|
+
}
|
|
1194
|
+
if (crosshair.priceActionButtonIcon !== "text" && crosshair.priceActionButtonText === "+") {
|
|
1195
|
+
const plusHalf = Math.max(3, Math.round(buttonSize * 0.22));
|
|
1196
|
+
const plusThickness = crosshair.priceActionButtonIcon === "plusThin" ? Math.max(1, Math.round(buttonSize * 0.07)) : Math.max(1, Math.round(buttonSize * 0.1));
|
|
1197
|
+
ctx.save();
|
|
1198
|
+
ctx.strokeStyle = labelTextColor;
|
|
1199
|
+
ctx.lineWidth = plusThickness;
|
|
1200
|
+
ctx.lineCap = "round";
|
|
1201
|
+
ctx.setLineDash([]);
|
|
1202
|
+
ctx.beginPath();
|
|
1203
|
+
ctx.moveTo(buttonCenterX - plusHalf, buttonCenterY);
|
|
1204
|
+
ctx.lineTo(buttonCenterX + plusHalf, buttonCenterY);
|
|
1205
|
+
ctx.moveTo(buttonCenterX, buttonCenterY - plusHalf);
|
|
1206
|
+
ctx.lineTo(buttonCenterX, buttonCenterY + plusHalf);
|
|
1207
|
+
ctx.stroke();
|
|
1168
1208
|
ctx.restore();
|
|
1209
|
+
} else {
|
|
1210
|
+
drawText(
|
|
1211
|
+
crosshair.priceActionButtonText,
|
|
1212
|
+
buttonCenterX,
|
|
1213
|
+
buttonCenterY,
|
|
1214
|
+
"center",
|
|
1215
|
+
"middle",
|
|
1216
|
+
labelTextColor
|
|
1217
|
+
);
|
|
1169
1218
|
}
|
|
1170
|
-
drawText(
|
|
1171
|
-
crosshair.priceActionButtonText,
|
|
1172
|
-
buttonX + buttonSize / 2,
|
|
1173
|
-
buttonY + buttonSize / 2,
|
|
1174
|
-
"center",
|
|
1175
|
-
"middle",
|
|
1176
|
-
crosshair.priceActionButtonTextColor
|
|
1177
|
-
);
|
|
1178
1219
|
crosshairPriceActionRegion = {
|
|
1179
|
-
x:
|
|
1180
|
-
y:
|
|
1181
|
-
width:
|
|
1182
|
-
height:
|
|
1220
|
+
x: containerX,
|
|
1221
|
+
y: containerY,
|
|
1222
|
+
width: containerWidth,
|
|
1223
|
+
height: labelHeight,
|
|
1183
1224
|
price: Number(hoverPrice.toFixed(mergedOptions.priceDecimals))
|
|
1184
1225
|
};
|
|
1185
1226
|
}
|
|
@@ -72,13 +72,10 @@ interface CrosshairOptions {
|
|
|
72
72
|
labelBorderWidth?: number;
|
|
73
73
|
labelBorderStyle?: "solid" | "dotted" | "dashed";
|
|
74
74
|
showPriceActionButton?: boolean;
|
|
75
|
+
priceActionButtonIcon?: "plus" | "plusThin" | "text";
|
|
75
76
|
priceActionButtonText?: string;
|
|
76
77
|
priceActionButtonSize?: number;
|
|
77
78
|
priceActionButtonGap?: number;
|
|
78
|
-
priceActionButtonBackgroundColor?: string;
|
|
79
|
-
priceActionButtonTextColor?: string;
|
|
80
|
-
priceActionButtonBorderColor?: string;
|
|
81
|
-
priceActionButtonBorderWidth?: number;
|
|
82
79
|
priceActionButtonRounded?: boolean;
|
|
83
80
|
priceActionButtonBorderRadius?: number;
|
|
84
81
|
}
|
|
@@ -29,15 +29,12 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
29
29
|
labelBorderWidth: 1,
|
|
30
30
|
labelBorderStyle: "solid",
|
|
31
31
|
showPriceActionButton: false,
|
|
32
|
+
priceActionButtonIcon: "plusThin",
|
|
32
33
|
priceActionButtonText: "+",
|
|
33
|
-
priceActionButtonSize:
|
|
34
|
-
priceActionButtonGap:
|
|
35
|
-
priceActionButtonBackgroundColor: "#1f2937",
|
|
36
|
-
priceActionButtonTextColor: "#e2e8f0",
|
|
37
|
-
priceActionButtonBorderColor: "#475569",
|
|
38
|
-
priceActionButtonBorderWidth: 1,
|
|
34
|
+
priceActionButtonSize: 16,
|
|
35
|
+
priceActionButtonGap: 4,
|
|
39
36
|
priceActionButtonRounded: true,
|
|
40
|
-
priceActionButtonBorderRadius:
|
|
37
|
+
priceActionButtonBorderRadius: 8
|
|
41
38
|
};
|
|
42
39
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
43
40
|
visible: false,
|
|
@@ -1127,35 +1124,79 @@ function createChart(element, options = {}) {
|
|
|
1127
1124
|
strokeCrosshairLabel(priceX, priceY, priceWidth);
|
|
1128
1125
|
drawText(priceText, priceX + labelPaddingX, priceY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1129
1126
|
if (crosshair.showPriceActionButton) {
|
|
1130
|
-
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12,
|
|
1127
|
+
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12, Math.max(12, labelHeight - 4));
|
|
1131
1128
|
const buttonGap = Math.max(0, Math.round(crosshair.priceActionButtonGap));
|
|
1132
|
-
const
|
|
1129
|
+
const containerPaddingX = 5;
|
|
1130
|
+
const containerWidth = buttonSize + containerPaddingX * 2;
|
|
1131
|
+
const containerX = priceX - buttonGap - containerWidth;
|
|
1132
|
+
const containerY = priceY;
|
|
1133
|
+
const buttonX = containerX + containerPaddingX;
|
|
1133
1134
|
const buttonY = priceY + (labelHeight - buttonSize) / 2;
|
|
1134
1135
|
const buttonRadius = crosshair.priceActionButtonRounded ? clamp(Math.round(crosshair.priceActionButtonBorderRadius), 0, buttonSize / 2) : 0;
|
|
1135
|
-
const buttonBorderWidth = Math.max(
|
|
1136
|
-
|
|
1137
|
-
|
|
1136
|
+
const buttonBorderWidth = Math.max(1, Math.round(labelBorderWidth || 1));
|
|
1137
|
+
const buttonCenterX = buttonX + buttonSize / 2;
|
|
1138
|
+
const buttonCenterY = buttonY + buttonSize / 2;
|
|
1139
|
+
const containerRadius = labelRadius;
|
|
1140
|
+
ctx.fillStyle = labelBackground;
|
|
1141
|
+
fillRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1142
|
+
if (labelBorderWidth > 0) {
|
|
1143
|
+
ctx.save();
|
|
1144
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1145
|
+
ctx.lineWidth = labelBorderWidth;
|
|
1146
|
+
ctx.setLineDash([]);
|
|
1147
|
+
strokeRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1148
|
+
ctx.restore();
|
|
1149
|
+
}
|
|
1138
1150
|
if (buttonBorderWidth > 0) {
|
|
1139
1151
|
ctx.save();
|
|
1140
|
-
ctx.strokeStyle =
|
|
1152
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1141
1153
|
ctx.lineWidth = buttonBorderWidth;
|
|
1142
1154
|
ctx.setLineDash([]);
|
|
1143
|
-
|
|
1155
|
+
if (crosshair.priceActionButtonRounded) {
|
|
1156
|
+
ctx.beginPath();
|
|
1157
|
+
ctx.arc(
|
|
1158
|
+
buttonCenterX,
|
|
1159
|
+
buttonCenterY,
|
|
1160
|
+
Math.max(1, buttonSize / 2 - buttonBorderWidth / 2),
|
|
1161
|
+
0,
|
|
1162
|
+
Math.PI * 2
|
|
1163
|
+
);
|
|
1164
|
+
ctx.stroke();
|
|
1165
|
+
} else {
|
|
1166
|
+
strokeRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, buttonRadius);
|
|
1167
|
+
}
|
|
1168
|
+
ctx.restore();
|
|
1169
|
+
}
|
|
1170
|
+
if (crosshair.priceActionButtonIcon !== "text" && crosshair.priceActionButtonText === "+") {
|
|
1171
|
+
const plusHalf = Math.max(3, Math.round(buttonSize * 0.22));
|
|
1172
|
+
const plusThickness = crosshair.priceActionButtonIcon === "plusThin" ? Math.max(1, Math.round(buttonSize * 0.07)) : Math.max(1, Math.round(buttonSize * 0.1));
|
|
1173
|
+
ctx.save();
|
|
1174
|
+
ctx.strokeStyle = labelTextColor;
|
|
1175
|
+
ctx.lineWidth = plusThickness;
|
|
1176
|
+
ctx.lineCap = "round";
|
|
1177
|
+
ctx.setLineDash([]);
|
|
1178
|
+
ctx.beginPath();
|
|
1179
|
+
ctx.moveTo(buttonCenterX - plusHalf, buttonCenterY);
|
|
1180
|
+
ctx.lineTo(buttonCenterX + plusHalf, buttonCenterY);
|
|
1181
|
+
ctx.moveTo(buttonCenterX, buttonCenterY - plusHalf);
|
|
1182
|
+
ctx.lineTo(buttonCenterX, buttonCenterY + plusHalf);
|
|
1183
|
+
ctx.stroke();
|
|
1144
1184
|
ctx.restore();
|
|
1185
|
+
} else {
|
|
1186
|
+
drawText(
|
|
1187
|
+
crosshair.priceActionButtonText,
|
|
1188
|
+
buttonCenterX,
|
|
1189
|
+
buttonCenterY,
|
|
1190
|
+
"center",
|
|
1191
|
+
"middle",
|
|
1192
|
+
labelTextColor
|
|
1193
|
+
);
|
|
1145
1194
|
}
|
|
1146
|
-
drawText(
|
|
1147
|
-
crosshair.priceActionButtonText,
|
|
1148
|
-
buttonX + buttonSize / 2,
|
|
1149
|
-
buttonY + buttonSize / 2,
|
|
1150
|
-
"center",
|
|
1151
|
-
"middle",
|
|
1152
|
-
crosshair.priceActionButtonTextColor
|
|
1153
|
-
);
|
|
1154
1195
|
crosshairPriceActionRegion = {
|
|
1155
|
-
x:
|
|
1156
|
-
y:
|
|
1157
|
-
width:
|
|
1158
|
-
height:
|
|
1196
|
+
x: containerX,
|
|
1197
|
+
y: containerY,
|
|
1198
|
+
width: containerWidth,
|
|
1199
|
+
height: labelHeight,
|
|
1159
1200
|
price: Number(hoverPrice.toFixed(mergedOptions.priceDecimals))
|
|
1160
1201
|
};
|
|
1161
1202
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -53,15 +53,12 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
53
53
|
labelBorderWidth: 1,
|
|
54
54
|
labelBorderStyle: "solid",
|
|
55
55
|
showPriceActionButton: false,
|
|
56
|
+
priceActionButtonIcon: "plusThin",
|
|
56
57
|
priceActionButtonText: "+",
|
|
57
|
-
priceActionButtonSize:
|
|
58
|
-
priceActionButtonGap:
|
|
59
|
-
priceActionButtonBackgroundColor: "#1f2937",
|
|
60
|
-
priceActionButtonTextColor: "#e2e8f0",
|
|
61
|
-
priceActionButtonBorderColor: "#475569",
|
|
62
|
-
priceActionButtonBorderWidth: 1,
|
|
58
|
+
priceActionButtonSize: 16,
|
|
59
|
+
priceActionButtonGap: 4,
|
|
63
60
|
priceActionButtonRounded: true,
|
|
64
|
-
priceActionButtonBorderRadius:
|
|
61
|
+
priceActionButtonBorderRadius: 8
|
|
65
62
|
};
|
|
66
63
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
67
64
|
visible: false,
|
|
@@ -1151,35 +1148,79 @@ function createChart(element, options = {}) {
|
|
|
1151
1148
|
strokeCrosshairLabel(priceX, priceY, priceWidth);
|
|
1152
1149
|
drawText(priceText, priceX + labelPaddingX, priceY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1153
1150
|
if (crosshair.showPriceActionButton) {
|
|
1154
|
-
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12,
|
|
1151
|
+
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12, Math.max(12, labelHeight - 4));
|
|
1155
1152
|
const buttonGap = Math.max(0, Math.round(crosshair.priceActionButtonGap));
|
|
1156
|
-
const
|
|
1153
|
+
const containerPaddingX = 5;
|
|
1154
|
+
const containerWidth = buttonSize + containerPaddingX * 2;
|
|
1155
|
+
const containerX = priceX - buttonGap - containerWidth;
|
|
1156
|
+
const containerY = priceY;
|
|
1157
|
+
const buttonX = containerX + containerPaddingX;
|
|
1157
1158
|
const buttonY = priceY + (labelHeight - buttonSize) / 2;
|
|
1158
1159
|
const buttonRadius = crosshair.priceActionButtonRounded ? clamp(Math.round(crosshair.priceActionButtonBorderRadius), 0, buttonSize / 2) : 0;
|
|
1159
|
-
const buttonBorderWidth = Math.max(
|
|
1160
|
-
|
|
1161
|
-
|
|
1160
|
+
const buttonBorderWidth = Math.max(1, Math.round(labelBorderWidth || 1));
|
|
1161
|
+
const buttonCenterX = buttonX + buttonSize / 2;
|
|
1162
|
+
const buttonCenterY = buttonY + buttonSize / 2;
|
|
1163
|
+
const containerRadius = labelRadius;
|
|
1164
|
+
ctx.fillStyle = labelBackground;
|
|
1165
|
+
fillRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1166
|
+
if (labelBorderWidth > 0) {
|
|
1167
|
+
ctx.save();
|
|
1168
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1169
|
+
ctx.lineWidth = labelBorderWidth;
|
|
1170
|
+
ctx.setLineDash([]);
|
|
1171
|
+
strokeRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1172
|
+
ctx.restore();
|
|
1173
|
+
}
|
|
1162
1174
|
if (buttonBorderWidth > 0) {
|
|
1163
1175
|
ctx.save();
|
|
1164
|
-
ctx.strokeStyle =
|
|
1176
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1165
1177
|
ctx.lineWidth = buttonBorderWidth;
|
|
1166
1178
|
ctx.setLineDash([]);
|
|
1167
|
-
|
|
1179
|
+
if (crosshair.priceActionButtonRounded) {
|
|
1180
|
+
ctx.beginPath();
|
|
1181
|
+
ctx.arc(
|
|
1182
|
+
buttonCenterX,
|
|
1183
|
+
buttonCenterY,
|
|
1184
|
+
Math.max(1, buttonSize / 2 - buttonBorderWidth / 2),
|
|
1185
|
+
0,
|
|
1186
|
+
Math.PI * 2
|
|
1187
|
+
);
|
|
1188
|
+
ctx.stroke();
|
|
1189
|
+
} else {
|
|
1190
|
+
strokeRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, buttonRadius);
|
|
1191
|
+
}
|
|
1192
|
+
ctx.restore();
|
|
1193
|
+
}
|
|
1194
|
+
if (crosshair.priceActionButtonIcon !== "text" && crosshair.priceActionButtonText === "+") {
|
|
1195
|
+
const plusHalf = Math.max(3, Math.round(buttonSize * 0.22));
|
|
1196
|
+
const plusThickness = crosshair.priceActionButtonIcon === "plusThin" ? Math.max(1, Math.round(buttonSize * 0.07)) : Math.max(1, Math.round(buttonSize * 0.1));
|
|
1197
|
+
ctx.save();
|
|
1198
|
+
ctx.strokeStyle = labelTextColor;
|
|
1199
|
+
ctx.lineWidth = plusThickness;
|
|
1200
|
+
ctx.lineCap = "round";
|
|
1201
|
+
ctx.setLineDash([]);
|
|
1202
|
+
ctx.beginPath();
|
|
1203
|
+
ctx.moveTo(buttonCenterX - plusHalf, buttonCenterY);
|
|
1204
|
+
ctx.lineTo(buttonCenterX + plusHalf, buttonCenterY);
|
|
1205
|
+
ctx.moveTo(buttonCenterX, buttonCenterY - plusHalf);
|
|
1206
|
+
ctx.lineTo(buttonCenterX, buttonCenterY + plusHalf);
|
|
1207
|
+
ctx.stroke();
|
|
1168
1208
|
ctx.restore();
|
|
1209
|
+
} else {
|
|
1210
|
+
drawText(
|
|
1211
|
+
crosshair.priceActionButtonText,
|
|
1212
|
+
buttonCenterX,
|
|
1213
|
+
buttonCenterY,
|
|
1214
|
+
"center",
|
|
1215
|
+
"middle",
|
|
1216
|
+
labelTextColor
|
|
1217
|
+
);
|
|
1169
1218
|
}
|
|
1170
|
-
drawText(
|
|
1171
|
-
crosshair.priceActionButtonText,
|
|
1172
|
-
buttonX + buttonSize / 2,
|
|
1173
|
-
buttonY + buttonSize / 2,
|
|
1174
|
-
"center",
|
|
1175
|
-
"middle",
|
|
1176
|
-
crosshair.priceActionButtonTextColor
|
|
1177
|
-
);
|
|
1178
1219
|
crosshairPriceActionRegion = {
|
|
1179
|
-
x:
|
|
1180
|
-
y:
|
|
1181
|
-
width:
|
|
1182
|
-
height:
|
|
1220
|
+
x: containerX,
|
|
1221
|
+
y: containerY,
|
|
1222
|
+
width: containerWidth,
|
|
1223
|
+
height: labelHeight,
|
|
1183
1224
|
price: Number(hoverPrice.toFixed(mergedOptions.priceDecimals))
|
|
1184
1225
|
};
|
|
1185
1226
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -72,13 +72,10 @@ interface CrosshairOptions {
|
|
|
72
72
|
labelBorderWidth?: number;
|
|
73
73
|
labelBorderStyle?: "solid" | "dotted" | "dashed";
|
|
74
74
|
showPriceActionButton?: boolean;
|
|
75
|
+
priceActionButtonIcon?: "plus" | "plusThin" | "text";
|
|
75
76
|
priceActionButtonText?: string;
|
|
76
77
|
priceActionButtonSize?: number;
|
|
77
78
|
priceActionButtonGap?: number;
|
|
78
|
-
priceActionButtonBackgroundColor?: string;
|
|
79
|
-
priceActionButtonTextColor?: string;
|
|
80
|
-
priceActionButtonBorderColor?: string;
|
|
81
|
-
priceActionButtonBorderWidth?: number;
|
|
82
79
|
priceActionButtonRounded?: boolean;
|
|
83
80
|
priceActionButtonBorderRadius?: number;
|
|
84
81
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -72,13 +72,10 @@ interface CrosshairOptions {
|
|
|
72
72
|
labelBorderWidth?: number;
|
|
73
73
|
labelBorderStyle?: "solid" | "dotted" | "dashed";
|
|
74
74
|
showPriceActionButton?: boolean;
|
|
75
|
+
priceActionButtonIcon?: "plus" | "plusThin" | "text";
|
|
75
76
|
priceActionButtonText?: string;
|
|
76
77
|
priceActionButtonSize?: number;
|
|
77
78
|
priceActionButtonGap?: number;
|
|
78
|
-
priceActionButtonBackgroundColor?: string;
|
|
79
|
-
priceActionButtonTextColor?: string;
|
|
80
|
-
priceActionButtonBorderColor?: string;
|
|
81
|
-
priceActionButtonBorderWidth?: number;
|
|
82
79
|
priceActionButtonRounded?: boolean;
|
|
83
80
|
priceActionButtonBorderRadius?: number;
|
|
84
81
|
}
|
package/dist/index.js
CHANGED
|
@@ -29,15 +29,12 @@ var DEFAULT_CROSSHAIR_OPTIONS = {
|
|
|
29
29
|
labelBorderWidth: 1,
|
|
30
30
|
labelBorderStyle: "solid",
|
|
31
31
|
showPriceActionButton: false,
|
|
32
|
+
priceActionButtonIcon: "plusThin",
|
|
32
33
|
priceActionButtonText: "+",
|
|
33
|
-
priceActionButtonSize:
|
|
34
|
-
priceActionButtonGap:
|
|
35
|
-
priceActionButtonBackgroundColor: "#1f2937",
|
|
36
|
-
priceActionButtonTextColor: "#e2e8f0",
|
|
37
|
-
priceActionButtonBorderColor: "#475569",
|
|
38
|
-
priceActionButtonBorderWidth: 1,
|
|
34
|
+
priceActionButtonSize: 16,
|
|
35
|
+
priceActionButtonGap: 4,
|
|
39
36
|
priceActionButtonRounded: true,
|
|
40
|
-
priceActionButtonBorderRadius:
|
|
37
|
+
priceActionButtonBorderRadius: 8
|
|
41
38
|
};
|
|
42
39
|
var DEFAULT_WATERMARK_OPTIONS = {
|
|
43
40
|
visible: false,
|
|
@@ -1127,35 +1124,79 @@ function createChart(element, options = {}) {
|
|
|
1127
1124
|
strokeCrosshairLabel(priceX, priceY, priceWidth);
|
|
1128
1125
|
drawText(priceText, priceX + labelPaddingX, priceY + labelHeight / 2, "left", "middle", labelTextColor);
|
|
1129
1126
|
if (crosshair.showPriceActionButton) {
|
|
1130
|
-
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12,
|
|
1127
|
+
const buttonSize = clamp(Math.round(crosshair.priceActionButtonSize), 12, Math.max(12, labelHeight - 4));
|
|
1131
1128
|
const buttonGap = Math.max(0, Math.round(crosshair.priceActionButtonGap));
|
|
1132
|
-
const
|
|
1129
|
+
const containerPaddingX = 5;
|
|
1130
|
+
const containerWidth = buttonSize + containerPaddingX * 2;
|
|
1131
|
+
const containerX = priceX - buttonGap - containerWidth;
|
|
1132
|
+
const containerY = priceY;
|
|
1133
|
+
const buttonX = containerX + containerPaddingX;
|
|
1133
1134
|
const buttonY = priceY + (labelHeight - buttonSize) / 2;
|
|
1134
1135
|
const buttonRadius = crosshair.priceActionButtonRounded ? clamp(Math.round(crosshair.priceActionButtonBorderRadius), 0, buttonSize / 2) : 0;
|
|
1135
|
-
const buttonBorderWidth = Math.max(
|
|
1136
|
-
|
|
1137
|
-
|
|
1136
|
+
const buttonBorderWidth = Math.max(1, Math.round(labelBorderWidth || 1));
|
|
1137
|
+
const buttonCenterX = buttonX + buttonSize / 2;
|
|
1138
|
+
const buttonCenterY = buttonY + buttonSize / 2;
|
|
1139
|
+
const containerRadius = labelRadius;
|
|
1140
|
+
ctx.fillStyle = labelBackground;
|
|
1141
|
+
fillRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1142
|
+
if (labelBorderWidth > 0) {
|
|
1143
|
+
ctx.save();
|
|
1144
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1145
|
+
ctx.lineWidth = labelBorderWidth;
|
|
1146
|
+
ctx.setLineDash([]);
|
|
1147
|
+
strokeRoundedRect(Math.round(containerX), Math.round(containerY), containerWidth, labelHeight, containerRadius);
|
|
1148
|
+
ctx.restore();
|
|
1149
|
+
}
|
|
1138
1150
|
if (buttonBorderWidth > 0) {
|
|
1139
1151
|
ctx.save();
|
|
1140
|
-
ctx.strokeStyle =
|
|
1152
|
+
ctx.strokeStyle = labelBorderColor;
|
|
1141
1153
|
ctx.lineWidth = buttonBorderWidth;
|
|
1142
1154
|
ctx.setLineDash([]);
|
|
1143
|
-
|
|
1155
|
+
if (crosshair.priceActionButtonRounded) {
|
|
1156
|
+
ctx.beginPath();
|
|
1157
|
+
ctx.arc(
|
|
1158
|
+
buttonCenterX,
|
|
1159
|
+
buttonCenterY,
|
|
1160
|
+
Math.max(1, buttonSize / 2 - buttonBorderWidth / 2),
|
|
1161
|
+
0,
|
|
1162
|
+
Math.PI * 2
|
|
1163
|
+
);
|
|
1164
|
+
ctx.stroke();
|
|
1165
|
+
} else {
|
|
1166
|
+
strokeRoundedRect(Math.round(buttonX), Math.round(buttonY), buttonSize, buttonSize, buttonRadius);
|
|
1167
|
+
}
|
|
1168
|
+
ctx.restore();
|
|
1169
|
+
}
|
|
1170
|
+
if (crosshair.priceActionButtonIcon !== "text" && crosshair.priceActionButtonText === "+") {
|
|
1171
|
+
const plusHalf = Math.max(3, Math.round(buttonSize * 0.22));
|
|
1172
|
+
const plusThickness = crosshair.priceActionButtonIcon === "plusThin" ? Math.max(1, Math.round(buttonSize * 0.07)) : Math.max(1, Math.round(buttonSize * 0.1));
|
|
1173
|
+
ctx.save();
|
|
1174
|
+
ctx.strokeStyle = labelTextColor;
|
|
1175
|
+
ctx.lineWidth = plusThickness;
|
|
1176
|
+
ctx.lineCap = "round";
|
|
1177
|
+
ctx.setLineDash([]);
|
|
1178
|
+
ctx.beginPath();
|
|
1179
|
+
ctx.moveTo(buttonCenterX - plusHalf, buttonCenterY);
|
|
1180
|
+
ctx.lineTo(buttonCenterX + plusHalf, buttonCenterY);
|
|
1181
|
+
ctx.moveTo(buttonCenterX, buttonCenterY - plusHalf);
|
|
1182
|
+
ctx.lineTo(buttonCenterX, buttonCenterY + plusHalf);
|
|
1183
|
+
ctx.stroke();
|
|
1144
1184
|
ctx.restore();
|
|
1185
|
+
} else {
|
|
1186
|
+
drawText(
|
|
1187
|
+
crosshair.priceActionButtonText,
|
|
1188
|
+
buttonCenterX,
|
|
1189
|
+
buttonCenterY,
|
|
1190
|
+
"center",
|
|
1191
|
+
"middle",
|
|
1192
|
+
labelTextColor
|
|
1193
|
+
);
|
|
1145
1194
|
}
|
|
1146
|
-
drawText(
|
|
1147
|
-
crosshair.priceActionButtonText,
|
|
1148
|
-
buttonX + buttonSize / 2,
|
|
1149
|
-
buttonY + buttonSize / 2,
|
|
1150
|
-
"center",
|
|
1151
|
-
"middle",
|
|
1152
|
-
crosshair.priceActionButtonTextColor
|
|
1153
|
-
);
|
|
1154
1195
|
crosshairPriceActionRegion = {
|
|
1155
|
-
x:
|
|
1156
|
-
y:
|
|
1157
|
-
width:
|
|
1158
|
-
height:
|
|
1196
|
+
x: containerX,
|
|
1197
|
+
y: containerY,
|
|
1198
|
+
width: containerWidth,
|
|
1199
|
+
height: labelHeight,
|
|
1159
1200
|
price: Number(hoverPrice.toFixed(mergedOptions.priceDecimals))
|
|
1160
1201
|
};
|
|
1161
1202
|
}
|
package/docs/API.md
CHANGED
|
@@ -95,15 +95,14 @@ Top-level options:
|
|
|
95
95
|
- `labelBorderWidth` (default `1`)
|
|
96
96
|
- `labelBorderStyle` (`"solid" | "dotted" | "dashed"`, default `"solid"`)
|
|
97
97
|
- `showPriceActionButton` (default `false`)
|
|
98
|
+
- `priceActionButtonIcon` (`"plus" | "plusThin" | "text"`, default `"plusThin"`)
|
|
98
99
|
- `priceActionButtonText` (default `"+"`)
|
|
99
|
-
- `priceActionButtonSize` (default `
|
|
100
|
-
- `priceActionButtonGap` (default `
|
|
101
|
-
- `priceActionButtonBackgroundColor` (default `#1f2937`)
|
|
102
|
-
- `priceActionButtonTextColor` (default `#e2e8f0`)
|
|
103
|
-
- `priceActionButtonBorderColor` (default `#475569`)
|
|
104
|
-
- `priceActionButtonBorderWidth` (default `1`)
|
|
100
|
+
- `priceActionButtonSize` (default `16`)
|
|
101
|
+
- `priceActionButtonGap` (default `4`)
|
|
105
102
|
- `priceActionButtonRounded` (default `true`; set `false` for square corners)
|
|
106
|
-
- `priceActionButtonBorderRadius` (default `
|
|
103
|
+
- `priceActionButtonBorderRadius` (default `8`)
|
|
104
|
+
|
|
105
|
+
Note: the button and its container automatically inherit crosshair label colors/border for a consistent `[button-box][label]` look.
|
|
107
106
|
|
|
108
107
|
### `WatermarkOptions`
|
|
109
108
|
|
package/docs/RECIPES.md
CHANGED
|
@@ -70,7 +70,7 @@ const chart = createChart(root, {
|
|
|
70
70
|
crosshair: {
|
|
71
71
|
showPriceActionButton: true,
|
|
72
72
|
priceActionButtonText: "+",
|
|
73
|
-
priceActionButtonGap:
|
|
73
|
+
priceActionButtonGap: 4
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
76
|
|
|
@@ -86,8 +86,7 @@ Square style example:
|
|
|
86
86
|
const chart = createChart(root, {
|
|
87
87
|
crosshair: {
|
|
88
88
|
showPriceActionButton: true,
|
|
89
|
-
priceActionButtonRounded: false
|
|
90
|
-
priceActionButtonBorderRadius: 0
|
|
89
|
+
priceActionButtonRounded: false
|
|
91
90
|
}
|
|
92
91
|
});
|
|
93
92
|
```
|