mirror of
https://github.com/viliusle/miniPaint.git
synced 2026-02-06 15:51:47 +00:00
#240: borders type migrated to effects.
This commit is contained in:
parent
1dab3914a2
commit
8a27ce1656
@ -712,7 +712,7 @@
|
||||
"rotate": 0,
|
||||
"data": null,
|
||||
"params": {
|
||||
"size": 7,
|
||||
"size": 15,
|
||||
"shadow": false
|
||||
},
|
||||
"status": null,
|
||||
@ -1588,7 +1588,7 @@
|
||||
{
|
||||
"id": 43,
|
||||
"parent_id": 0,
|
||||
"name": "Cog #43",
|
||||
"name": "Cog",
|
||||
"type": "cog",
|
||||
"link": null,
|
||||
"x": 50,
|
||||
@ -1617,7 +1617,7 @@
|
||||
{
|
||||
"id": 44,
|
||||
"parent_id": 0,
|
||||
"name": "Tear #44",
|
||||
"name": "Tear",
|
||||
"type": "tear",
|
||||
"link": null,
|
||||
"x": 140,
|
||||
@ -1652,7 +1652,7 @@
|
||||
{
|
||||
"id": 45,
|
||||
"parent_id": 0,
|
||||
"name": "Moon #45",
|
||||
"name": "Moon",
|
||||
"type": "moon",
|
||||
"link": null,
|
||||
"x": 220,
|
||||
@ -1687,7 +1687,7 @@
|
||||
{
|
||||
"id": 46,
|
||||
"parent_id": 0,
|
||||
"name": "Callout #46",
|
||||
"name": "Callout",
|
||||
"type": "callout",
|
||||
"link": null,
|
||||
"x": 300,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "miniPaint",
|
||||
"version": "4.7.1",
|
||||
"version": "4.8",
|
||||
"author": "Vilius L.",
|
||||
"description": "Online graphics editing tool lets create, edit images using HTML5 technologies.",
|
||||
"keywords": [
|
||||
|
||||
@ -472,6 +472,11 @@ const menuDefinition = [
|
||||
ellipsis: true,
|
||||
target: 'effects/black_and_white.black_and_white'
|
||||
},
|
||||
{
|
||||
name: 'Borders',
|
||||
ellipsis: true,
|
||||
target: 'effects/borders.borders'
|
||||
},
|
||||
{
|
||||
name: 'Blueprint',
|
||||
target: 'effects/blueprint.blueprint'
|
||||
@ -575,11 +580,6 @@ const menuDefinition = [
|
||||
{
|
||||
name: 'Tools',
|
||||
children: [
|
||||
{
|
||||
name: 'Borders',
|
||||
ellipsis: true,
|
||||
target: 'tools/borders.borders'
|
||||
},
|
||||
{
|
||||
name: 'Sprites',
|
||||
target: 'tools/sprites.sprites'
|
||||
|
||||
@ -329,6 +329,9 @@ class Base_layers_class {
|
||||
//apply post-filters
|
||||
for (var i in object.filters) {
|
||||
var filter = object.filters[i];
|
||||
if(filter.id == this.disabled_filter_id){
|
||||
continue;
|
||||
}
|
||||
filter.name = filter.name.replace('drop-shadow', 'shadow');
|
||||
|
||||
//find filter
|
||||
@ -722,6 +725,32 @@ class Base_layers_class {
|
||||
this.disabled_filter_id = filter_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* finds layer filter by filter ID
|
||||
*
|
||||
* @param filter_id
|
||||
* @param filter_name
|
||||
* @param layer_id
|
||||
* @returns {object}
|
||||
*/
|
||||
find_filter_by_id(filter_id, filter_name, layer_id) {
|
||||
if(typeof layer_id == 'undefined'){
|
||||
var layer = config.layer;
|
||||
}
|
||||
else{
|
||||
var layer = this.get_layer(layer_id);
|
||||
}
|
||||
|
||||
var filter = {};
|
||||
for(var i in layer.filters){
|
||||
if(layer.filters[i].name == filter_name && layer.filters[i].id == filter_id) {
|
||||
return layer.filters[i].params;
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Base_layers_class;
|
||||
|
||||
@ -66,17 +66,6 @@ class Effects_common_class {
|
||||
return value;
|
||||
}
|
||||
|
||||
find_filter_by_id(filter_id, filter_name) {
|
||||
var filter = {};
|
||||
for(var i in config.layer.filters){
|
||||
if(config.layer.filters[i].name == filter_name && config.layer.filters[i].id == filter_id) {
|
||||
return config.layer.filters[i].params;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Effects_common_class;
|
||||
107
src/js/modules/effects/borders.js
Normal file
107
src/js/modules/effects/borders.js
Normal file
@ -0,0 +1,107 @@
|
||||
import app from './../../app.js';
|
||||
import config from './../../config.js';
|
||||
import Base_layers_class from './../../core/base-layers.js';
|
||||
import Dialog_class from './../../libs/popup.js';
|
||||
import alertify from './../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
import Effects_browser_class from "./browser";
|
||||
|
||||
class Effects_borders_class {
|
||||
|
||||
constructor() {
|
||||
this.POP = new Dialog_class();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
this.Effects_browser = new Effects_browser_class();
|
||||
}
|
||||
|
||||
borders(filter_id) {
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var _this = this;
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'borders');
|
||||
|
||||
var settings = {
|
||||
title: 'Borders',
|
||||
params: [
|
||||
{name: "color", title: "Color:", value: filter.color ??= config.COLOR, type: 'color'},
|
||||
{name: "size", title: "Size:", value: filter.size ??= 10},
|
||||
],
|
||||
on_finish: function (params) {
|
||||
var target = Math.min(config.WIDTH, config.HEIGHT);
|
||||
_this.add_borders(params, filter_id);
|
||||
},
|
||||
};
|
||||
var rotate = config.layer.rotate;
|
||||
config.layer.rotate = 0;
|
||||
this.Base_layers.disable_filter(filter_id);
|
||||
this.POP.show(settings);
|
||||
config.layer.rotate = rotate;
|
||||
this.Base_layers.disable_filter(null);
|
||||
}
|
||||
|
||||
demo(canvas_id, canvas_thumb){
|
||||
var canvas = document.getElementById(canvas_id);
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
//draw
|
||||
ctx.drawImage(canvas_thumb,
|
||||
5, 5,
|
||||
this.Effects_browser.preview_width - 10, this.Effects_browser.preview_height - 10);
|
||||
|
||||
//add borders
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = 10;
|
||||
ctx.beginPath();
|
||||
ctx.rect(0, 0, canvas.width, canvas.height);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
render_pre(ctx, data) {
|
||||
|
||||
}
|
||||
|
||||
render_post(ctx, data, layer){
|
||||
var size = Math.max(0, data.params.size);
|
||||
|
||||
var x = layer.x;
|
||||
var y = layer.y;
|
||||
var width = parseInt(layer.width);
|
||||
var height = parseInt(layer.height);
|
||||
|
||||
//legacy check
|
||||
if(x == null) x = 0;
|
||||
if(y == null) y = 0;
|
||||
if(!width) width = config.WIDTH;
|
||||
if(!height) height = config.HEIGHT;
|
||||
|
||||
ctx.save();
|
||||
|
||||
//set styles
|
||||
ctx.strokeStyle = data.params.color;
|
||||
ctx.lineWidth = size;
|
||||
|
||||
//draw with rotation support
|
||||
ctx.translate(layer.x + width / 2, layer.y + height / 2);
|
||||
ctx.rotate(layer.rotate * Math.PI / 180);
|
||||
var x_new = -width / 2;
|
||||
var y_new = -height / 2;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.rect(x_new - size * 0.5, y_new - size * 0.5, width + size, height + size);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
add_borders(params, filter_id) {
|
||||
//apply effect
|
||||
return app.State.do_action(
|
||||
new app.Actions.Add_layer_filter_action(config.layer.id, 'borders', params, filter_id)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Effects_borders_class;
|
||||
@ -1,16 +1,24 @@
|
||||
import config from '../../../config.js';
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Dialog_class from '../../../libs/popup.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_blur_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.POP = new Dialog_class();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
blur(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'blur');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'blur');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 5, range: [0, 50]},
|
||||
|
||||
@ -1,9 +1,21 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_brightness_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
brightness(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'brightness');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'brightness');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 50, range: [-100, 100]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_contrast_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
contrast(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'contrast');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'contrast');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 40, range: [-100, 100]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_grayscale_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
grayscale(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'grayscale');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'grayscale');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 100, range: [0, 100]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_hueRotate_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
hue_rotate(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'hue-rotate');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'hue-rotate');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Degree:", value: filter.value ??= 90, range: [0, 360]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_invert_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
invert(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'invert');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'invert');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 100, range: [0, 100]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_saturate_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
saturate(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'saturate');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'saturate');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= -50, range: [-100, 100]},
|
||||
|
||||
@ -1,9 +1,22 @@
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import config from "../../../config";
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_sepia_class extends Effects_common_class {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
sepia(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'sepia');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'sepia');
|
||||
|
||||
var params = [
|
||||
{name: "value", title: "Percentage:", value: filter.value ??= 60, range: [0, 100]},
|
||||
|
||||
@ -2,6 +2,8 @@ import config from '../../../config.js';
|
||||
import Effects_common_class from '../abstract/css.js';
|
||||
import Dialog_class from '../../../libs/popup.js';
|
||||
import Effects_browser_class from '../browser.js';
|
||||
import Base_layers_class from './../../../core/base-layers.js';
|
||||
import alertify from './../../../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
class Effects_brightness_class extends Effects_common_class {
|
||||
|
||||
@ -9,11 +11,17 @@ class Effects_brightness_class extends Effects_common_class {
|
||||
super();
|
||||
this.POP = new Dialog_class();
|
||||
this.Effects_browser = new Effects_browser_class();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
this.preview_padding = 20;
|
||||
}
|
||||
|
||||
shadow(filter_id) {
|
||||
var filter = this.find_filter_by_id(filter_id, 'shadow');
|
||||
if (config.layer.type == null) {
|
||||
alertify.error('Layer is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = this.Base_layers.find_filter_by_id(filter_id, 'shadow');
|
||||
|
||||
var params = [
|
||||
{name: "x", title: "Offset X:", value: filter.x ??= 10, range: [-100, 100]},
|
||||
|
||||
@ -555,6 +555,27 @@ class File_open_class {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(json.info.version < "4.8"){
|
||||
//migrate "borders" layer to rectangle
|
||||
for (var i in json.layers) {
|
||||
var old_type = json.layers[i].type;
|
||||
|
||||
if(old_type == 'borders'){
|
||||
json.layers[i].type = 'rectangle';
|
||||
json.layers[i].name += ' (legacy)';
|
||||
json.layers[i].params = {
|
||||
radius: 0,
|
||||
fill: false,
|
||||
square: false,
|
||||
border_size: json.layers[i].params.size,
|
||||
border: true,
|
||||
border_color: json.layers[i].color,
|
||||
fill_color: "#000000",
|
||||
};
|
||||
json.layers[i].render_function = ["rectangle", "render"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const actions = [];
|
||||
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
import app from './../../app.js';
|
||||
import config from './../../config.js';
|
||||
import Base_layers_class from './../../core/base-layers.js';
|
||||
import Dialog_class from './../../libs/popup.js';
|
||||
|
||||
class Tools_borders_class {
|
||||
|
||||
constructor() {
|
||||
this.POP = new Dialog_class();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
}
|
||||
|
||||
borders() {
|
||||
var _this = this;
|
||||
|
||||
var settings = {
|
||||
title: 'Borders',
|
||||
preview: true,
|
||||
on_change: function (params, canvas_preview, w, h) {
|
||||
var target = Math.min(w, h);
|
||||
params.size = Math.round(target / 100 * params.size);
|
||||
_this.preview_borders(params, canvas_preview, w, h);
|
||||
},
|
||||
params: [
|
||||
{name: "color", title: "Color:", value: config.COLOR, type: 'color'},
|
||||
{name: "shadow", title: "Shadow:", value: false},
|
||||
{name: "size", title: "Size:", value: "5", range: [1, 100]},
|
||||
],
|
||||
on_finish: function (params) {
|
||||
var target = Math.min(config.WIDTH, config.HEIGHT);
|
||||
params.size = Math.round(target / 100 * params.size);
|
||||
_this.add_borders(params);
|
||||
},
|
||||
};
|
||||
this.POP.show(settings);
|
||||
}
|
||||
|
||||
preview_borders(params, ctx, width, height) {
|
||||
var size = params.size;
|
||||
var color = params.color;
|
||||
var color = params.color;
|
||||
|
||||
ctx.save();
|
||||
ctx.lineWidth = size;
|
||||
if (params.shadow === true) {
|
||||
//with shadow
|
||||
ctx.beginPath();
|
||||
ctx.shadowColor = color;
|
||||
ctx.shadowBlur = size;
|
||||
ctx.rect(-size / 2, -size / 2, width + size, height + size);
|
||||
ctx.stroke();
|
||||
ctx.stroke();
|
||||
ctx.stroke();
|
||||
}
|
||||
else {
|
||||
ctx.strokeStyle = color;
|
||||
ctx.rect(0, 0, width, height);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
add_borders(params) {
|
||||
//create borders layer
|
||||
this.layer = {
|
||||
name: 'Borders',
|
||||
type: 'borders',
|
||||
render_function: ['borders', 'render'],
|
||||
params: {size: params.size, shadow: params.shadow},
|
||||
color: params.color,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: config.WIDTH,
|
||||
height: config.HEIGHT,
|
||||
is_vector: true,
|
||||
};
|
||||
app.State.do_action(
|
||||
new app.Actions.Bundle_action('add_borders', 'Add Borders', [
|
||||
new app.Actions.Insert_layer_action(this.layer)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Tools_borders_class;
|
||||
@ -1,60 +0,0 @@
|
||||
import config from './../config.js';
|
||||
import Base_tools_class from './../core/base-tools.js';
|
||||
import Base_layers_class from './../core/base-layers.js';
|
||||
|
||||
class Borders_class extends Base_tools_class {
|
||||
|
||||
constructor(ctx) {
|
||||
super();
|
||||
this.Base_layers = new Base_layers_class();
|
||||
this.ctx = ctx;
|
||||
this.name = 'borders';
|
||||
this.layer = {};
|
||||
}
|
||||
|
||||
load() {
|
||||
//nothing
|
||||
}
|
||||
|
||||
render(ctx, layer) {
|
||||
var params = layer.params;
|
||||
var size = params.size;
|
||||
|
||||
var x = layer.x;
|
||||
var y = layer.y;
|
||||
var width = parseInt(layer.width);
|
||||
var height = parseInt(layer.height);
|
||||
|
||||
//legcy check
|
||||
if(x == null) x = 0;
|
||||
if(y == null) y = 0;
|
||||
if(!width) width = config.WIDTH;
|
||||
if(!height) height = config.HEIGHT;
|
||||
|
||||
ctx.save();
|
||||
|
||||
//set styles
|
||||
ctx.strokeStyle = layer.color;
|
||||
ctx.lineWidth = size;
|
||||
|
||||
if (params.shadow === true) {
|
||||
//with shadow
|
||||
ctx.beginPath();
|
||||
ctx.shadowColor = layer.color;
|
||||
ctx.shadowBlur = size * config.ZOOM;
|
||||
ctx.rect(x -size / 2, y -size / 2, width + size, height + size);
|
||||
ctx.stroke();
|
||||
ctx.stroke();
|
||||
ctx.stroke();
|
||||
}
|
||||
else {
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, width, height);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
}
|
||||
;
|
||||
export default Borders_class;
|
||||
Loading…
Reference in New Issue
Block a user