@oliasoft-open-source/charts-library 5.10.0-beta-2 → 5.10.0-beta-4
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/index.d.ts +7 -7
- package/dist/index.js +148 -64
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1116,6 +1116,13 @@ export declare type UnusedParameter = unknown;
|
|
|
1116
1116
|
export { }
|
|
1117
1117
|
|
|
1118
1118
|
|
|
1119
|
+
declare module 'chart.js' {
|
|
1120
|
+
interface PluginOptionsByType<TType extends ChartType> {
|
|
1121
|
+
annotationDraggerPlugin?: AnnotationDraggerPluginOptions;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
|
|
1119
1126
|
/**
|
|
1120
1127
|
* Vertical Markers Plugin
|
|
1121
1128
|
*
|
|
@@ -1176,10 +1183,3 @@ declare module 'chart.js' {
|
|
|
1176
1183
|
};
|
|
1177
1184
|
}
|
|
1178
1185
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
declare module 'chart.js' {
|
|
1182
|
-
interface PluginOptionsByType<TType extends ChartType> {
|
|
1183
|
-
annotationDraggerPlugin?: AnnotationDraggerPluginOptions;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
package/dist/index.js
CHANGED
|
@@ -20889,13 +20889,18 @@ var DEFAULT_VERTICAL_OFFSET = -18;
|
|
|
20889
20889
|
var DEFAULT_ROW_GAP = 22;
|
|
20890
20890
|
var DEFAULT_ITEM_GAP = 8;
|
|
20891
20891
|
var DEFAULT_OVERLAP_ONLY_ITEM_GAP = 14;
|
|
20892
|
-
var
|
|
20893
|
-
var DEFAULT_SIDE_SPREAD_MAX = 48;
|
|
20892
|
+
var DEFAULT_LANE_GAP = 12;
|
|
20894
20893
|
var clamp$1 = (value, min, max) => {
|
|
20895
20894
|
if (Number.isNaN(value)) return min;
|
|
20896
20895
|
if (min > max) return min;
|
|
20897
20896
|
return Math.min(Math.max(value, min), max);
|
|
20898
20897
|
};
|
|
20898
|
+
var clampRelaxed = (value, min, max) => {
|
|
20899
|
+
if (min <= max) return clamp$1(value, min, max);
|
|
20900
|
+
if (value < max) return max;
|
|
20901
|
+
if (value > min) return min;
|
|
20902
|
+
return value;
|
|
20903
|
+
};
|
|
20899
20904
|
var getNumericValue = (value, fallback = 0) => {
|
|
20900
20905
|
return typeof value === "number" ? value : fallback;
|
|
20901
20906
|
};
|
|
@@ -21099,15 +21104,6 @@ var getOverlappingCalloutIds = (chart) => {
|
|
|
21099
21104
|
});
|
|
21100
21105
|
return overlappingIds;
|
|
21101
21106
|
};
|
|
21102
|
-
var getOccupiedOriginalLabelRects = (chart, area, overlappingIds) => {
|
|
21103
|
-
return ((chart?.options)?.annotations?.annotationsData ?? []).flatMap((annotation, index) => {
|
|
21104
|
-
const calloutCfg = getCalloutCfg(annotation);
|
|
21105
|
-
const id = `callout-annotation-${index}`;
|
|
21106
|
-
if (!calloutCfg?.enabled || !calloutCfg?.onlyWhenOverlapping) return [];
|
|
21107
|
-
if (overlappingIds.has(id)) return [];
|
|
21108
|
-
return [getOriginalLabelRect(chart, area, annotation, index)];
|
|
21109
|
-
});
|
|
21110
|
-
};
|
|
21111
21107
|
var isCalloutOverlapping = (ctx, refAnnotation, index) => {
|
|
21112
21108
|
const chart = getChartFromCtx$1(ctx);
|
|
21113
21109
|
if (!getCalloutCfg(refAnnotation)?.onlyWhenOverlapping) return true;
|
|
@@ -21140,7 +21136,6 @@ var getCalloutItems = (chart, area) => {
|
|
|
21140
21136
|
const calloutCfg = getCalloutCfg(annotation);
|
|
21141
21137
|
const id = `callout-annotation-${index}`;
|
|
21142
21138
|
if (!calloutCfg?.enabled) return [];
|
|
21143
|
-
if (calloutCfg?.onlyWhenOverlapping && !overlappingIds.has(id)) return [];
|
|
21144
21139
|
const size = estimateLabelSize(chart, annotation, calloutCfg);
|
|
21145
21140
|
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
21146
21141
|
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
@@ -21162,6 +21157,7 @@ var getCalloutItems = (chart, area) => {
|
|
|
21162
21157
|
width: size.width,
|
|
21163
21158
|
height: size.height,
|
|
21164
21159
|
isFixed: hasStoredX && hasStoredY,
|
|
21160
|
+
isOverlapping: overlappingIds.has(id),
|
|
21165
21161
|
overlapOnly: Boolean(calloutCfg?.onlyWhenOverlapping),
|
|
21166
21162
|
minX: area.left + margin + size.width / 2,
|
|
21167
21163
|
maxX: area.right - margin - size.width / 2,
|
|
@@ -21192,7 +21188,79 @@ var getLayoutGap = (item) => {
|
|
|
21192
21188
|
var getLayoutOrderY = (item) => {
|
|
21193
21189
|
return item.isFixed ? item.preferredY : item.anchorY;
|
|
21194
21190
|
};
|
|
21191
|
+
var intervalsOverlap = (top, bottom, otherTop, otherBottom) => {
|
|
21192
|
+
return !(bottom <= otherTop || top >= otherBottom);
|
|
21193
|
+
};
|
|
21194
|
+
var assignLabelColumns = (items, layout) => {
|
|
21195
|
+
const columns = [];
|
|
21196
|
+
const hasPrimaryColumn = items.some((item) => {
|
|
21197
|
+
return !item.overlapOnly || !item.isOverlapping;
|
|
21198
|
+
});
|
|
21199
|
+
[...items].sort((left, right) => getLayoutOrderY(left) - getLayoutOrderY(right)).forEach((item) => {
|
|
21200
|
+
const current = layout.get(item.id);
|
|
21201
|
+
if (!current) return;
|
|
21202
|
+
const top = current.yValue - item.height / 2 - getLayoutGap(item) / 2;
|
|
21203
|
+
const bottom = current.yValue + item.height / 2 + getLayoutGap(item) / 2;
|
|
21204
|
+
let columnIndex = hasPrimaryColumn && item.overlapOnly && item.isOverlapping ? 1 : 0;
|
|
21205
|
+
while (true) {
|
|
21206
|
+
if (!(columns[columnIndex] ?? []).some((placed) => {
|
|
21207
|
+
return intervalsOverlap(top, bottom, placed.top, placed.bottom);
|
|
21208
|
+
})) {
|
|
21209
|
+
if (!columns[columnIndex]) columns[columnIndex] = [];
|
|
21210
|
+
columns[columnIndex].push({
|
|
21211
|
+
id: item.id,
|
|
21212
|
+
top,
|
|
21213
|
+
bottom,
|
|
21214
|
+
width: item.width
|
|
21215
|
+
});
|
|
21216
|
+
break;
|
|
21217
|
+
}
|
|
21218
|
+
columnIndex += 1;
|
|
21219
|
+
}
|
|
21220
|
+
});
|
|
21221
|
+
return columns;
|
|
21222
|
+
};
|
|
21223
|
+
var applyLaneLayout = (items, layout, occupiedRects) => {
|
|
21224
|
+
if (items.length <= 1) return;
|
|
21225
|
+
const side = items[0]?.side;
|
|
21226
|
+
const columns = assignLabelColumns(items, layout);
|
|
21227
|
+
const getCurrentRect = (item) => {
|
|
21228
|
+
const centerX = layout.get(item.id)?.xValue ?? item.preferredX;
|
|
21229
|
+
return {
|
|
21230
|
+
left: centerX - item.width / 2,
|
|
21231
|
+
right: centerX + item.width / 2
|
|
21232
|
+
};
|
|
21233
|
+
};
|
|
21234
|
+
const referenceItems = items.filter((item) => {
|
|
21235
|
+
return columns[0]?.some((placed) => placed.id === item.id);
|
|
21236
|
+
});
|
|
21237
|
+
const referenceRects = referenceItems.length ? referenceItems : items;
|
|
21238
|
+
const baseEdge = side === "right" ? occupiedRects.length ? Math.min(...occupiedRects.map((rect) => rect.left)) - DEFAULT_LANE_GAP : Math.min(...referenceRects.map((item) => getCurrentRect(item).left)) : occupiedRects.length ? Math.max(...occupiedRects.map((rect) => rect.right)) + DEFAULT_LANE_GAP : Math.max(...referenceRects.map((item) => getCurrentRect(item).right));
|
|
21239
|
+
columns.forEach((column, columnIndex) => {
|
|
21240
|
+
const columnWidth = Math.max(...column.map((placed) => placed.width));
|
|
21241
|
+
column?.forEach((placed) => {
|
|
21242
|
+
const item = items.find((candidate) => candidate.id === placed.id);
|
|
21243
|
+
const current = layout.get(placed.id);
|
|
21244
|
+
if (!item || !current) return;
|
|
21245
|
+
const xValue = side === "right" ? baseEdge - columnIndex * (columnWidth + DEFAULT_LANE_GAP) - item.width / 2 : baseEdge + columnIndex * (columnWidth + DEFAULT_LANE_GAP) + item.width / 2;
|
|
21246
|
+
layout.set(placed.id, {
|
|
21247
|
+
...current,
|
|
21248
|
+
xValue: clamp$1(xValue, item.minX, item.maxX)
|
|
21249
|
+
});
|
|
21250
|
+
});
|
|
21251
|
+
});
|
|
21252
|
+
};
|
|
21253
|
+
var getOrderBounds = (item, occupiedRects) => {
|
|
21254
|
+
const previousRect = [...occupiedRects].filter((rect) => rect.centerY <= item.anchorY).at(-1);
|
|
21255
|
+
const nextRect = occupiedRects.find((rect) => rect.centerY >= item.anchorY);
|
|
21256
|
+
const gap = getLayoutGap(item);
|
|
21257
|
+
return {
|
|
21258
|
+
minCenter: previousRect ? previousRect.bottom + gap + item.height / 2 : item.minY,
|
|
21259
|
+
maxCenter: nextRect ? nextRect.top - gap - item.height / 2 : item.maxY
|
|
21260
|
+
};
|
|
21261
|
+
};
|
|
21195
21262
|
var layoutSide = (items, occupiedRects = []) => {
|
|
21263
|
+
const sortedOccupiedRects = [...occupiedRects].sort((left, right) => left.centerY - right.centerY);
|
|
21196
21264
|
const sorted = [...items].sort((left, right) => getLayoutOrderY(left) - getLayoutOrderY(right));
|
|
21197
21265
|
const result = /* @__PURE__ */ new Map();
|
|
21198
21266
|
if (!sorted.filter((item) => !item.isFixed).length) {
|
|
@@ -21223,12 +21291,16 @@ var layoutSide = (items, occupiedRects = []) => {
|
|
|
21223
21291
|
previousBottom = yValue + item.height / 2;
|
|
21224
21292
|
return;
|
|
21225
21293
|
}
|
|
21226
|
-
const
|
|
21227
|
-
|
|
21228
|
-
|
|
21294
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21295
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter);
|
|
21296
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter, previousBottom + item.height / 2 + getLayoutGap(item));
|
|
21297
|
+
let yValue = clampRelaxed(item.preferredY, minCenter, maxCenter);
|
|
21298
|
+
let overlappingRect = overlapsOccupiedRect(yValue, item.height, sortedOccupiedRects);
|
|
21229
21299
|
while (overlappingRect) {
|
|
21230
|
-
|
|
21231
|
-
|
|
21300
|
+
const nextCandidate = overlappingRect.bottom + getLayoutGap(item) + item.height / 2;
|
|
21301
|
+
if (nextCandidate === yValue) break;
|
|
21302
|
+
yValue = clampRelaxed(nextCandidate, minCenter, maxCenter);
|
|
21303
|
+
overlappingRect = overlapsOccupiedRect(yValue, item.height, sortedOccupiedRects);
|
|
21232
21304
|
}
|
|
21233
21305
|
result.set(item.id, {
|
|
21234
21306
|
xValue: item.preferredX,
|
|
@@ -21244,54 +21316,67 @@ var layoutSide = (items, occupiedRects = []) => {
|
|
|
21244
21316
|
nextTop = current.yValue - item.height / 2;
|
|
21245
21317
|
return;
|
|
21246
21318
|
}
|
|
21247
|
-
const
|
|
21248
|
-
const
|
|
21319
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21320
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter, nextTop - item.height / 2 - getLayoutGap(item));
|
|
21321
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter);
|
|
21322
|
+
const yValue = clampRelaxed(current.yValue, minCenter, maxCenter);
|
|
21249
21323
|
result.set(item.id, {
|
|
21250
21324
|
...current,
|
|
21251
21325
|
yValue
|
|
21252
21326
|
});
|
|
21253
21327
|
nextTop = yValue - item.height / 2;
|
|
21254
21328
|
});
|
|
21255
|
-
|
|
21256
|
-
|
|
21329
|
+
previousBottom = Number.NEGATIVE_INFINITY;
|
|
21330
|
+
sorted.forEach((item) => {
|
|
21331
|
+
const current = result.get(item.id);
|
|
21332
|
+
if (!current) return;
|
|
21333
|
+
if (item.isFixed) {
|
|
21334
|
+
previousBottom = current.yValue + item.height / 2;
|
|
21335
|
+
return;
|
|
21336
|
+
}
|
|
21337
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21338
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter);
|
|
21339
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter, previousBottom + item.height / 2 + getLayoutGap(item));
|
|
21340
|
+
const yValue = clampRelaxed(current.yValue, minCenter, maxCenter);
|
|
21341
|
+
result.set(item.id, {
|
|
21342
|
+
...current,
|
|
21343
|
+
yValue
|
|
21344
|
+
});
|
|
21345
|
+
previousBottom = yValue + item.height / 2;
|
|
21257
21346
|
});
|
|
21258
|
-
if (
|
|
21259
|
-
const
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
return
|
|
21264
|
-
})
|
|
21265
|
-
|
|
21266
|
-
const current = result.get(item.id);
|
|
21267
|
-
if (!current) return;
|
|
21268
|
-
const spreadOffset = Math.min(index * DEFAULT_SIDE_SPREAD_STEP, DEFAULT_SIDE_SPREAD_MAX);
|
|
21269
|
-
const direction = item.side === "right" ? -1 : 1;
|
|
21270
|
-
const alignedXValue = item.side === "right" ? sharedOuterEdge - item.width / 2 : sharedOuterEdge + item.width / 2;
|
|
21347
|
+
if (sorted.some((item) => item.overlapOnly)) {
|
|
21348
|
+
const untouchedPrimary = sorted.filter((item) => {
|
|
21349
|
+
return !item.isFixed && item.overlapOnly && !item.isOverlapping;
|
|
21350
|
+
});
|
|
21351
|
+
const secondaryMovable = sorted.filter((item) => {
|
|
21352
|
+
return !item.isFixed && item.overlapOnly && item.isOverlapping;
|
|
21353
|
+
});
|
|
21354
|
+
untouchedPrimary.forEach((item) => {
|
|
21271
21355
|
result.set(item.id, {
|
|
21272
|
-
|
|
21273
|
-
|
|
21356
|
+
xValue: item.preferredX,
|
|
21357
|
+
yValue: clamp$1(item.preferredY, item.minY, item.maxY)
|
|
21274
21358
|
});
|
|
21275
21359
|
});
|
|
21360
|
+
if (secondaryMovable.length) applyLaneLayout(secondaryMovable, result, untouchedPrimary.map((item) => {
|
|
21361
|
+
const current = result.get(item.id);
|
|
21362
|
+
const centerX = current?.xValue ?? item.preferredX;
|
|
21363
|
+
const centerY = current?.yValue ?? item.preferredY;
|
|
21364
|
+
return {
|
|
21365
|
+
top: centerY - item.height / 2,
|
|
21366
|
+
bottom: centerY + item.height / 2,
|
|
21367
|
+
centerY,
|
|
21368
|
+
left: centerX - item.width / 2,
|
|
21369
|
+
right: centerX + item.width / 2
|
|
21370
|
+
};
|
|
21371
|
+
}));
|
|
21276
21372
|
return result;
|
|
21277
21373
|
}
|
|
21278
|
-
sorted.
|
|
21279
|
-
const current = result.get(item.id);
|
|
21280
|
-
if (!current || item.isFixed) return;
|
|
21281
|
-
const spreadOffset = Math.min(index * DEFAULT_SIDE_SPREAD_STEP, DEFAULT_SIDE_SPREAD_MAX);
|
|
21282
|
-
const direction = item.side === "right" ? -1 : 1;
|
|
21283
|
-
const xValue = clamp$1(current.xValue + direction * spreadOffset, item.minX, item.maxX);
|
|
21284
|
-
result.set(item.id, {
|
|
21285
|
-
...current,
|
|
21286
|
-
xValue
|
|
21287
|
-
});
|
|
21288
|
-
});
|
|
21374
|
+
applyLaneLayout(sorted.filter((item) => !item.isFixed), result, []);
|
|
21289
21375
|
return result;
|
|
21290
21376
|
};
|
|
21291
21377
|
var getCalloutLayoutPixels = (chart) => {
|
|
21292
21378
|
const area = chart?.chartArea;
|
|
21293
21379
|
if (!chart || !area) return /* @__PURE__ */ new Map();
|
|
21294
|
-
const occupiedRects = getOccupiedOriginalLabelRects(chart, area, getOverlappingCalloutIds(chart));
|
|
21295
21380
|
const grouped = getCalloutItems(chart, area).map((item) => {
|
|
21296
21381
|
const xValue = clamp$1(item.preferredX, item.minX, item.maxX);
|
|
21297
21382
|
return {
|
|
@@ -21305,14 +21390,8 @@ var getCalloutLayoutPixels = (chart) => {
|
|
|
21305
21390
|
left: [],
|
|
21306
21391
|
right: []
|
|
21307
21392
|
});
|
|
21308
|
-
const leftLayout = layoutSide(grouped.left,
|
|
21309
|
-
|
|
21310
|
-
bottom: rect.bottom
|
|
21311
|
-
})));
|
|
21312
|
-
const rightLayout = layoutSide(grouped.right, occupiedRects.filter((rect) => rect.side === "right").map((rect) => ({
|
|
21313
|
-
top: rect.top,
|
|
21314
|
-
bottom: rect.bottom
|
|
21315
|
-
})));
|
|
21393
|
+
const leftLayout = layoutSide(grouped.left, []);
|
|
21394
|
+
const rightLayout = layoutSide(grouped.right, []);
|
|
21316
21395
|
return new Map([...leftLayout.entries(), ...rightLayout.entries()]);
|
|
21317
21396
|
};
|
|
21318
21397
|
var getCalloutLayout = (ctx, refAnnotation, index) => {
|
|
@@ -21686,11 +21765,7 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21686
21765
|
...baseRest,
|
|
21687
21766
|
label: {
|
|
21688
21767
|
...label,
|
|
21689
|
-
display: (
|
|
21690
|
-
if (!(refAnnotation.display ?? true)) return false;
|
|
21691
|
-
if (!calloutCfg?.onlyWhenOverlapping) return false;
|
|
21692
|
-
return !isCalloutOverlapping(ctx, refAnnotation, index);
|
|
21693
|
-
}
|
|
21768
|
+
display: () => false
|
|
21694
21769
|
}
|
|
21695
21770
|
};
|
|
21696
21771
|
const color = calloutCfg?.color ?? "hsl(60, 10.34482759%, 12.5%)";
|
|
@@ -21722,7 +21797,7 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21722
21797
|
display: (ctx) => {
|
|
21723
21798
|
if (!(refAnnotation.display ?? true)) return false;
|
|
21724
21799
|
if (!isCalloutAnchorInChartArea(ctx, refAnnotation, calloutCfg.margin ?? 0)) return false;
|
|
21725
|
-
return
|
|
21800
|
+
return true;
|
|
21726
21801
|
},
|
|
21727
21802
|
xValue: (ctx) => {
|
|
21728
21803
|
const persistenceId = getChartFromCtx(ctx)?.options?.persistenceId;
|
|
@@ -21755,7 +21830,10 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21755
21830
|
return onCalloutDragEnd(coords, refAnnotation);
|
|
21756
21831
|
} : void 0,
|
|
21757
21832
|
calloutConnector: {
|
|
21758
|
-
enabled:
|
|
21833
|
+
enabled: ({ chart }) => {
|
|
21834
|
+
if (!calloutCfg?.onlyWhenOverlapping) return true;
|
|
21835
|
+
return isCalloutOverlapping({ chart }, refAnnotation, index);
|
|
21836
|
+
},
|
|
21759
21837
|
fromId: baseId,
|
|
21760
21838
|
strokeStyle,
|
|
21761
21839
|
lineWidth,
|
|
@@ -22724,11 +22802,17 @@ var calloutConnectorPlugin = {
|
|
|
22724
22802
|
if (!raw) return;
|
|
22725
22803
|
(Array.isArray(raw) ? raw : Object.values(raw)).forEach((opt) => {
|
|
22726
22804
|
const connector = opt?.calloutConnector;
|
|
22727
|
-
if (!connector || !
|
|
22805
|
+
if (!connector || !opt?.id) return;
|
|
22728
22806
|
const labelEl = elements.find((el) => el.options && el.options.id === opt.id);
|
|
22729
22807
|
const fromEl = elements.find((el) => el.options && el.options.id === connector.fromId);
|
|
22730
22808
|
if (!labelEl || !fromEl) return;
|
|
22731
22809
|
if (labelEl.options?.display === false) return;
|
|
22810
|
+
if (!(typeof connector.enabled === "function" ? connector.enabled({
|
|
22811
|
+
chart,
|
|
22812
|
+
labelEl,
|
|
22813
|
+
fromEl,
|
|
22814
|
+
option: opt
|
|
22815
|
+
}) : connector.enabled !== false)) return;
|
|
22732
22816
|
const { startX, startY, endX, endY, tickStartX, tickStartY, tickEndX, tickEndY } = computeConnectorPoints(fromEl, labelEl, connector) ?? {};
|
|
22733
22817
|
const ctx = chart?.ctx;
|
|
22734
22818
|
const strokeStyle = connector?.strokeStyle ?? "rgba(120, 126, 138, 0.9)";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oliasoft-open-source/charts-library",
|
|
3
|
-
"version": "5.10.0-beta-
|
|
3
|
+
"version": "5.10.0-beta-4",
|
|
4
4
|
"description": "React Chart Library (based on Chart.js and react-chart-js-2)",
|
|
5
5
|
"homepage": "https://gitlab.com/oliasoft-open-source/charts-library",
|
|
6
6
|
"bugs": {
|