İlk temizlik tamamlandı bir önceki projeden
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
'use strict';
|
||||
|
||||
var defaults = require('../core/core.defaults');
|
||||
var Element = require('../core/core.element');
|
||||
var helpers = require('../helpers/index');
|
||||
var TAU = Math.PI * 2;
|
||||
|
||||
defaults._set('global', {
|
||||
elements: {
|
||||
arc: {
|
||||
backgroundColor: defaults.global.defaultColor,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
borderAlign: 'center'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function clipArc(ctx, arc) {
|
||||
var startAngle = arc.startAngle;
|
||||
var endAngle = arc.endAngle;
|
||||
var pixelMargin = arc.pixelMargin;
|
||||
var angleMargin = pixelMargin / arc.outerRadius;
|
||||
var x = arc.x;
|
||||
var y = arc.y;
|
||||
|
||||
// Draw an inner border by cliping the arc and drawing a double-width border
|
||||
// Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, arc.outerRadius, startAngle - angleMargin, endAngle + angleMargin);
|
||||
if (arc.innerRadius > pixelMargin) {
|
||||
angleMargin = pixelMargin / arc.innerRadius;
|
||||
ctx.arc(x, y, arc.innerRadius - pixelMargin, endAngle + angleMargin, startAngle - angleMargin, true);
|
||||
} else {
|
||||
ctx.arc(x, y, pixelMargin, endAngle + Math.PI / 2, startAngle - Math.PI / 2);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
}
|
||||
|
||||
function drawFullCircleBorders(ctx, vm, arc, inner) {
|
||||
var endAngle = arc.endAngle;
|
||||
var i;
|
||||
|
||||
if (inner) {
|
||||
arc.endAngle = arc.startAngle + TAU;
|
||||
clipArc(ctx, arc);
|
||||
arc.endAngle = endAngle;
|
||||
if (arc.endAngle === arc.startAngle && arc.fullCircles) {
|
||||
arc.endAngle += TAU;
|
||||
arc.fullCircles--;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.x, arc.y, arc.innerRadius, arc.startAngle + TAU, arc.startAngle, true);
|
||||
for (i = 0; i < arc.fullCircles; ++i) {
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.startAngle + TAU);
|
||||
for (i = 0; i < arc.fullCircles; ++i) {
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
function drawBorder(ctx, vm, arc) {
|
||||
var inner = vm.borderAlign === 'inner';
|
||||
|
||||
if (inner) {
|
||||
ctx.lineWidth = vm.borderWidth * 2;
|
||||
ctx.lineJoin = 'round';
|
||||
} else {
|
||||
ctx.lineWidth = vm.borderWidth;
|
||||
ctx.lineJoin = 'bevel';
|
||||
}
|
||||
|
||||
if (arc.fullCircles) {
|
||||
drawFullCircleBorders(ctx, vm, arc, inner);
|
||||
}
|
||||
|
||||
if (inner) {
|
||||
clipArc(ctx, arc);
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.endAngle);
|
||||
ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
module.exports = Element.extend({
|
||||
_type: 'arc',
|
||||
|
||||
inLabelRange: function(mouseX) {
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
inRange: function(chartX, chartY) {
|
||||
var vm = this._view;
|
||||
|
||||
if (vm) {
|
||||
var pointRelativePosition = helpers.getAngleFromPoint(vm, {x: chartX, y: chartY});
|
||||
var angle = pointRelativePosition.angle;
|
||||
var distance = pointRelativePosition.distance;
|
||||
|
||||
// Sanitise angle range
|
||||
var startAngle = vm.startAngle;
|
||||
var endAngle = vm.endAngle;
|
||||
while (endAngle < startAngle) {
|
||||
endAngle += TAU;
|
||||
}
|
||||
while (angle > endAngle) {
|
||||
angle -= TAU;
|
||||
}
|
||||
while (angle < startAngle) {
|
||||
angle += TAU;
|
||||
}
|
||||
|
||||
// Check if within the range of the open/close angle
|
||||
var betweenAngles = (angle >= startAngle && angle <= endAngle);
|
||||
var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
|
||||
|
||||
return (betweenAngles && withinRadius);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getCenterPoint: function() {
|
||||
var vm = this._view;
|
||||
var halfAngle = (vm.startAngle + vm.endAngle) / 2;
|
||||
var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;
|
||||
return {
|
||||
x: vm.x + Math.cos(halfAngle) * halfRadius,
|
||||
y: vm.y + Math.sin(halfAngle) * halfRadius
|
||||
};
|
||||
},
|
||||
|
||||
getArea: function() {
|
||||
var vm = this._view;
|
||||
return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2));
|
||||
},
|
||||
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2);
|
||||
var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
|
||||
|
||||
return {
|
||||
x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
|
||||
y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
|
||||
};
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0;
|
||||
var arc = {
|
||||
x: vm.x,
|
||||
y: vm.y,
|
||||
innerRadius: vm.innerRadius,
|
||||
outerRadius: Math.max(vm.outerRadius - pixelMargin, 0),
|
||||
pixelMargin: pixelMargin,
|
||||
startAngle: vm.startAngle,
|
||||
endAngle: vm.endAngle,
|
||||
fullCircles: Math.floor(vm.circumference / TAU)
|
||||
};
|
||||
var i;
|
||||
|
||||
ctx.save();
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor;
|
||||
ctx.strokeStyle = vm.borderColor;
|
||||
|
||||
if (arc.fullCircles) {
|
||||
arc.endAngle = arc.startAngle + TAU;
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);
|
||||
ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
|
||||
ctx.closePath();
|
||||
for (i = 0; i < arc.fullCircles; ++i) {
|
||||
ctx.fill();
|
||||
}
|
||||
arc.endAngle = arc.startAngle + vm.circumference % TAU;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);
|
||||
ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
if (vm.borderWidth) {
|
||||
drawBorder(ctx, vm, arc);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
var defaults = require('../core/core.defaults');
|
||||
var Element = require('../core/core.element');
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
var valueOrDefault = helpers.valueOrDefault;
|
||||
|
||||
var defaultColor = defaults.global.defaultColor;
|
||||
|
||||
defaults._set('global', {
|
||||
elements: {
|
||||
line: {
|
||||
tension: 0.4,
|
||||
backgroundColor: defaultColor,
|
||||
borderWidth: 3,
|
||||
borderColor: defaultColor,
|
||||
borderCapStyle: 'butt',
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
borderJoinStyle: 'miter',
|
||||
capBezierPoints: true,
|
||||
fill: true, // do we fill in the area between the line and its base axis
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Element.extend({
|
||||
_type: 'line',
|
||||
|
||||
draw: function() {
|
||||
var me = this;
|
||||
var vm = me._view;
|
||||
var ctx = me._chart.ctx;
|
||||
var spanGaps = vm.spanGaps;
|
||||
var points = me._children.slice(); // clone array
|
||||
var globalDefaults = defaults.global;
|
||||
var globalOptionLineElements = globalDefaults.elements.line;
|
||||
var lastDrawnIndex = -1;
|
||||
var closePath = me._loop;
|
||||
var index, previous, currentVM;
|
||||
|
||||
if (!points.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (me._loop) {
|
||||
for (index = 0; index < points.length; ++index) {
|
||||
previous = helpers.previousItem(points, index);
|
||||
// If the line has an open path, shift the point array
|
||||
if (!points[index]._view.skip && previous._view.skip) {
|
||||
points = points.slice(index).concat(points.slice(0, index));
|
||||
closePath = spanGaps;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If the line has a close path, add the first point again
|
||||
if (closePath) {
|
||||
points.push(points[0]);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Stroke Line Options
|
||||
ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
|
||||
|
||||
// IE 9 and 10 do not support line dash
|
||||
if (ctx.setLineDash) {
|
||||
ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
|
||||
}
|
||||
|
||||
ctx.lineDashOffset = valueOrDefault(vm.borderDashOffset, globalOptionLineElements.borderDashOffset);
|
||||
ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
|
||||
ctx.lineWidth = valueOrDefault(vm.borderWidth, globalOptionLineElements.borderWidth);
|
||||
ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
|
||||
|
||||
// Stroke Line
|
||||
ctx.beginPath();
|
||||
|
||||
// First point moves to it's starting position no matter what
|
||||
currentVM = points[0]._view;
|
||||
if (!currentVM.skip) {
|
||||
ctx.moveTo(currentVM.x, currentVM.y);
|
||||
lastDrawnIndex = 0;
|
||||
}
|
||||
|
||||
for (index = 1; index < points.length; ++index) {
|
||||
currentVM = points[index]._view;
|
||||
previous = lastDrawnIndex === -1 ? helpers.previousItem(points, index) : points[lastDrawnIndex];
|
||||
|
||||
if (!currentVM.skip) {
|
||||
if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
|
||||
// There was a gap and this is the first point after the gap
|
||||
ctx.moveTo(currentVM.x, currentVM.y);
|
||||
} else {
|
||||
// Line to next point
|
||||
helpers.canvas.lineTo(ctx, previous._view, currentVM);
|
||||
}
|
||||
lastDrawnIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
if (closePath) {
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
var defaults = require('../core/core.defaults');
|
||||
var Element = require('../core/core.element');
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
var valueOrDefault = helpers.valueOrDefault;
|
||||
|
||||
var defaultColor = defaults.global.defaultColor;
|
||||
|
||||
defaults._set('global', {
|
||||
elements: {
|
||||
point: {
|
||||
radius: 3,
|
||||
pointStyle: 'circle',
|
||||
backgroundColor: defaultColor,
|
||||
borderColor: defaultColor,
|
||||
borderWidth: 1,
|
||||
// Hover
|
||||
hitRadius: 1,
|
||||
hoverRadius: 4,
|
||||
hoverBorderWidth: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function xRange(mouseX) {
|
||||
var vm = this._view;
|
||||
return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false;
|
||||
}
|
||||
|
||||
function yRange(mouseY) {
|
||||
var vm = this._view;
|
||||
return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false;
|
||||
}
|
||||
|
||||
module.exports = Element.extend({
|
||||
_type: 'point',
|
||||
|
||||
inRange: function(mouseX, mouseY) {
|
||||
var vm = this._view;
|
||||
return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
|
||||
},
|
||||
|
||||
inLabelRange: xRange,
|
||||
inXRange: xRange,
|
||||
inYRange: yRange,
|
||||
|
||||
getCenterPoint: function() {
|
||||
var vm = this._view;
|
||||
return {
|
||||
x: vm.x,
|
||||
y: vm.y
|
||||
};
|
||||
},
|
||||
|
||||
getArea: function() {
|
||||
return Math.PI * Math.pow(this._view.radius, 2);
|
||||
},
|
||||
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
return {
|
||||
x: vm.x,
|
||||
y: vm.y,
|
||||
padding: vm.radius + vm.borderWidth
|
||||
};
|
||||
},
|
||||
|
||||
draw: function(chartArea) {
|
||||
var vm = this._view;
|
||||
var ctx = this._chart.ctx;
|
||||
var pointStyle = vm.pointStyle;
|
||||
var rotation = vm.rotation;
|
||||
var radius = vm.radius;
|
||||
var x = vm.x;
|
||||
var y = vm.y;
|
||||
var globalDefaults = defaults.global;
|
||||
var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow
|
||||
|
||||
if (vm.skip) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clipping for Points.
|
||||
if (chartArea === undefined || helpers.canvas._isPointInArea(vm, chartArea)) {
|
||||
ctx.strokeStyle = vm.borderColor || defaultColor;
|
||||
ctx.lineWidth = valueOrDefault(vm.borderWidth, globalDefaults.elements.point.borderWidth);
|
||||
ctx.fillStyle = vm.backgroundColor || defaultColor;
|
||||
helpers.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,213 @@
|
||||
'use strict';
|
||||
|
||||
var defaults = require('../core/core.defaults');
|
||||
var Element = require('../core/core.element');
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
var defaultColor = defaults.global.defaultColor;
|
||||
|
||||
defaults._set('global', {
|
||||
elements: {
|
||||
rectangle: {
|
||||
backgroundColor: defaultColor,
|
||||
borderColor: defaultColor,
|
||||
borderSkipped: 'bottom',
|
||||
borderWidth: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function isVertical(vm) {
|
||||
return vm && vm.width !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the bounds of the bar regardless of the orientation
|
||||
* @param bar {Chart.Element.Rectangle} the bar
|
||||
* @return {Bounds} bounds of the bar
|
||||
* @private
|
||||
*/
|
||||
function getBarBounds(vm) {
|
||||
var x1, x2, y1, y2, half;
|
||||
|
||||
if (isVertical(vm)) {
|
||||
half = vm.width / 2;
|
||||
x1 = vm.x - half;
|
||||
x2 = vm.x + half;
|
||||
y1 = Math.min(vm.y, vm.base);
|
||||
y2 = Math.max(vm.y, vm.base);
|
||||
} else {
|
||||
half = vm.height / 2;
|
||||
x1 = Math.min(vm.x, vm.base);
|
||||
x2 = Math.max(vm.x, vm.base);
|
||||
y1 = vm.y - half;
|
||||
y2 = vm.y + half;
|
||||
}
|
||||
|
||||
return {
|
||||
left: x1,
|
||||
top: y1,
|
||||
right: x2,
|
||||
bottom: y2
|
||||
};
|
||||
}
|
||||
|
||||
function swap(orig, v1, v2) {
|
||||
return orig === v1 ? v2 : orig === v2 ? v1 : orig;
|
||||
}
|
||||
|
||||
function parseBorderSkipped(vm) {
|
||||
var edge = vm.borderSkipped;
|
||||
var res = {};
|
||||
|
||||
if (!edge) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (vm.horizontal) {
|
||||
if (vm.base > vm.x) {
|
||||
edge = swap(edge, 'left', 'right');
|
||||
}
|
||||
} else if (vm.base < vm.y) {
|
||||
edge = swap(edge, 'bottom', 'top');
|
||||
}
|
||||
|
||||
res[edge] = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
function parseBorderWidth(vm, maxW, maxH) {
|
||||
var value = vm.borderWidth;
|
||||
var skip = parseBorderSkipped(vm);
|
||||
var t, r, b, l;
|
||||
|
||||
if (helpers.isObject(value)) {
|
||||
t = +value.top || 0;
|
||||
r = +value.right || 0;
|
||||
b = +value.bottom || 0;
|
||||
l = +value.left || 0;
|
||||
} else {
|
||||
t = r = b = l = +value || 0;
|
||||
}
|
||||
|
||||
return {
|
||||
t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t,
|
||||
r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r,
|
||||
b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b,
|
||||
l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l
|
||||
};
|
||||
}
|
||||
|
||||
function boundingRects(vm) {
|
||||
var bounds = getBarBounds(vm);
|
||||
var width = bounds.right - bounds.left;
|
||||
var height = bounds.bottom - bounds.top;
|
||||
var border = parseBorderWidth(vm, width / 2, height / 2);
|
||||
|
||||
return {
|
||||
outer: {
|
||||
x: bounds.left,
|
||||
y: bounds.top,
|
||||
w: width,
|
||||
h: height
|
||||
},
|
||||
inner: {
|
||||
x: bounds.left + border.l,
|
||||
y: bounds.top + border.t,
|
||||
w: width - border.l - border.r,
|
||||
h: height - border.t - border.b
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function inRange(vm, x, y) {
|
||||
var skipX = x === null;
|
||||
var skipY = y === null;
|
||||
var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm);
|
||||
|
||||
return bounds
|
||||
&& (skipX || x >= bounds.left && x <= bounds.right)
|
||||
&& (skipY || y >= bounds.top && y <= bounds.bottom);
|
||||
}
|
||||
|
||||
module.exports = Element.extend({
|
||||
_type: 'rectangle',
|
||||
|
||||
draw: function() {
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
var rects = boundingRects(vm);
|
||||
var outer = rects.outer;
|
||||
var inner = rects.inner;
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor;
|
||||
ctx.fillRect(outer.x, outer.y, outer.w, outer.h);
|
||||
|
||||
if (outer.w === inner.w && outer.h === inner.h) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(outer.x, outer.y, outer.w, outer.h);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = vm.borderColor;
|
||||
ctx.rect(inner.x, inner.y, inner.w, inner.h);
|
||||
ctx.fill('evenodd');
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
height: function() {
|
||||
var vm = this._view;
|
||||
return vm.base - vm.y;
|
||||
},
|
||||
|
||||
inRange: function(mouseX, mouseY) {
|
||||
return inRange(this._view, mouseX, mouseY);
|
||||
},
|
||||
|
||||
inLabelRange: function(mouseX, mouseY) {
|
||||
var vm = this._view;
|
||||
return isVertical(vm)
|
||||
? inRange(vm, mouseX, null)
|
||||
: inRange(vm, null, mouseY);
|
||||
},
|
||||
|
||||
inXRange: function(mouseX) {
|
||||
return inRange(this._view, mouseX, null);
|
||||
},
|
||||
|
||||
inYRange: function(mouseY) {
|
||||
return inRange(this._view, null, mouseY);
|
||||
},
|
||||
|
||||
getCenterPoint: function() {
|
||||
var vm = this._view;
|
||||
var x, y;
|
||||
if (isVertical(vm)) {
|
||||
x = vm.x;
|
||||
y = (vm.y + vm.base) / 2;
|
||||
} else {
|
||||
x = (vm.x + vm.base) / 2;
|
||||
y = vm.y;
|
||||
}
|
||||
|
||||
return {x: x, y: y};
|
||||
},
|
||||
|
||||
getArea: function() {
|
||||
var vm = this._view;
|
||||
|
||||
return isVertical(vm)
|
||||
? vm.width * Math.abs(vm.y - vm.base)
|
||||
: vm.height * Math.abs(vm.x - vm.base);
|
||||
},
|
||||
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
return {
|
||||
x: vm.x,
|
||||
y: vm.y
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {};
|
||||
module.exports.Arc = require('./element.arc');
|
||||
module.exports.Line = require('./element.line');
|
||||
module.exports.Point = require('./element.point');
|
||||
module.exports.Rectangle = require('./element.rectangle');
|
||||
Reference in New Issue
Block a user