Compare commits
546 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f4ca0c96c | ||
|
|
6d0b95e50c | ||
|
|
c48593190f | ||
|
|
054d89cccd | ||
|
|
d32e925125 | ||
|
|
352a231973 | ||
|
|
e38f1040c0 | ||
|
|
faf9a2afc4 | ||
|
|
c47dcbf6e5 | ||
|
|
96d9e12017 | ||
|
|
9e57e09371 | ||
|
|
2ba14fe4ef | ||
|
|
df0f259172 | ||
|
|
f4aba673d4 | ||
|
|
7c2c056642 | ||
|
|
f22cb46515 | ||
|
|
1fce319dc9 | ||
|
|
1fed01dde0 | ||
|
|
1e11f8d590 | ||
|
|
b34b031f3d | ||
|
|
85e850b40d | ||
|
|
cf894ac34a | ||
|
|
79c79ca4a5 | ||
|
|
95b496c480 | ||
|
|
1032804da4 | ||
|
|
8189d9c4a6 | ||
|
|
153134809b | ||
|
|
b3cb94e7bd | ||
|
|
dcc3d08d33 | ||
|
|
8f255597e4 | ||
|
|
eff3ce5894 | ||
|
|
cef7e6f79c | ||
|
|
48bda1d41f | ||
|
|
53d3ef7f83 | ||
|
|
7ca23d9e07 | ||
|
|
d36fbadd86 | ||
|
|
9522fd4343 | ||
|
|
7b8ad8b6ac | ||
|
|
9dd908c390 | ||
|
|
e5af391390 | ||
|
|
39f8d5ed52 | ||
|
|
b71c64b227 | ||
|
|
e5022921e2 | ||
|
|
f5f79d055f | ||
|
|
69b08a1326 | ||
|
|
bf0b62e6c5 | ||
|
|
f9015fe58d | ||
|
|
736aea47e2 | ||
|
|
b424482e4d | ||
|
|
35acc344a8 | ||
|
|
fe020842b0 | ||
|
|
0bc28fcbc4 | ||
|
|
abc3704c9a | ||
|
|
ee7d8325cd | ||
|
|
790c1e100e | ||
|
|
f1eb954087 | ||
|
|
b9693d21db | ||
|
|
ddf97ca4c4 | ||
|
|
62ca359776 | ||
|
|
bbb17d5dc3 | ||
|
|
fc0ccf3fa7 | ||
|
|
3df83776c7 | ||
|
|
5350803089 | ||
|
|
b3ca4dbd49 | ||
|
|
92975b2dca | ||
|
|
59f80c16bc | ||
|
|
342086f3f0 | ||
|
|
a72e3f12a3 | ||
|
|
ce570658f7 | ||
|
|
1a9ea280e4 | ||
|
|
b249e2b70b | ||
|
|
ec27681450 | ||
|
|
caf9f03f1a | ||
|
|
9556235502 | ||
|
|
797f946aa8 | ||
|
|
885a162558 | ||
|
|
7e75b4c353 | ||
|
|
f1be2f3145 | ||
|
|
81afb22a39 | ||
|
|
0855adb797 | ||
|
|
7c5b8101e6 | ||
|
|
dae340d0ea | ||
|
|
7d54a2d73e | ||
|
|
a596d2e59b | ||
|
|
e37651a4d9 | ||
|
|
35adb236ad | ||
|
|
b9ab37497a | ||
|
|
7b1fac9fb5 | ||
|
|
170124f041 | ||
|
|
e8c784e2bd | ||
|
|
ff82f90435 | ||
|
|
db8d0af14f | ||
|
|
2fa0c079e9 | ||
|
|
5f32f3797e | ||
|
|
e2a7446725 | ||
|
|
82f641631b | ||
|
|
70938e3452 | ||
|
|
7cc20aaaa6 | ||
|
|
72647e4d0a | ||
|
|
46928a2b18 | ||
|
|
877d35ebfb | ||
|
|
0ea34e8997 | ||
|
|
5658ae0684 | ||
|
|
45103ef618 | ||
|
|
4c6204224d | ||
|
|
d71629e49a | ||
|
|
c2aa4594e3 | ||
|
|
f1e512ae2f | ||
|
|
d23b5e83fb | ||
|
|
ee53f86e83 | ||
|
|
c07d9f8c9f | ||
|
|
2c4717a9f9 | ||
|
|
68b6835c54 | ||
|
|
1951006cf9 | ||
|
|
e32e7d6a6e | ||
|
|
076ceae74e | ||
|
|
aa48644325 | ||
|
|
c9f93538df | ||
|
|
47dbbea3bc | ||
|
|
ae900ac17e | ||
|
|
dde4ab4f26 | ||
|
|
e062b421da | ||
|
|
5d489738f6 | ||
|
|
e6923445dc | ||
|
|
497b0054a5 | ||
|
|
a6e52102d2 | ||
|
|
6b22b1f80b | ||
|
|
c720c768bc | ||
|
|
8b8aa3cd38 | ||
|
|
b528b5d9d2 | ||
|
|
12e2e37a8a | ||
|
|
cd2bd75804 | ||
|
|
997089d506 | ||
|
|
fa6d7b69c7 | ||
|
|
b7a8e5eb9a | ||
|
|
28671d130c | ||
|
|
baba50ab7c | ||
|
|
1c67672af5 | ||
|
|
2fe3781be0 | ||
|
|
6008e723fc | ||
|
|
50b5c29e0e | ||
|
|
f8689b180f | ||
|
|
3ba9005fbb | ||
|
|
8884e13a9b | ||
|
|
43088b19c2 | ||
|
|
1c3568079d | ||
|
|
0fa15bd180 | ||
|
|
16f19baf47 | ||
|
|
e52df1c649 | ||
|
|
8a27ce1656 | ||
|
|
1dab3914a2 | ||
|
|
7c4455f3d9 | ||
|
|
7e0d519e3c | ||
|
|
1699063904 | ||
|
|
6bb57b1590 | ||
|
|
433d702b0b | ||
|
|
dc0c5de453 | ||
|
|
87bc43970c | ||
|
|
d680289719 | ||
|
|
4dcdb0fcbc | ||
|
|
928dcc218a | ||
|
|
13c8912343 | ||
|
|
4241260361 | ||
|
|
98730c226d | ||
|
|
b47682c93a | ||
|
|
6f56d1ba35 | ||
|
|
4567f00493 | ||
|
|
28dd0ffa6a | ||
|
|
91d2b8e9d0 | ||
|
|
d9364248ef | ||
|
|
6b7fd928f3 | ||
|
|
a4e4d3aef5 | ||
|
|
5f83a58ef8 | ||
|
|
c02f662932 | ||
|
|
450c4db2e8 | ||
|
|
9e2cdac358 | ||
|
|
d4a48230d7 | ||
|
|
08aa91d82b | ||
|
|
cdc51cbfce | ||
|
|
0e5bc1219c | ||
|
|
ad0558f71d | ||
|
|
994552c387 | ||
|
|
97872d230e | ||
|
|
d471fc41fc | ||
|
|
67aae07781 | ||
|
|
e6901014c6 | ||
|
|
b346e60e90 | ||
|
|
f0d3d06f7b | ||
|
|
ae39fd5f0b | ||
|
|
f2cf1b6737 | ||
|
|
ef6e45caa3 | ||
|
|
481fd5ae4c | ||
|
|
7e7454087a | ||
|
|
02bcee0e6a | ||
|
|
17b410fe44 | ||
|
|
5ba3fbe4aa | ||
|
|
2cd9227e4d | ||
|
|
7507599d72 | ||
|
|
80ad57f7a8 | ||
|
|
c64af51d1c | ||
|
|
ea86375ed4 | ||
|
|
7f545c5ed1 | ||
|
|
4eb75b3b26 | ||
|
|
4b0bf4a781 | ||
|
|
3b16567be5 | ||
|
|
c77ce6aa54 | ||
|
|
6c80a30e51 | ||
|
|
5ee74e261f | ||
|
|
07c03377e5 | ||
|
|
b79bf2b020 | ||
|
|
fdaac09784 | ||
|
|
23c9f40bda | ||
|
|
d398cd7117 | ||
|
|
5948e6bb8a | ||
|
|
59b19f69a8 | ||
|
|
3f8b4f4058 | ||
|
|
0dfd4b8db3 | ||
|
|
fa14d98d58 | ||
|
|
5831aac2ef | ||
|
|
8034826180 | ||
|
|
c2c21f4d54 | ||
|
|
f837b0c40c | ||
|
|
7f1e7e6242 | ||
|
|
10dd17363e | ||
|
|
6f7829ceb1 | ||
|
|
6867e4edca | ||
|
|
bee177d4aa | ||
|
|
f737c2779d | ||
|
|
4a150c7d53 | ||
|
|
203185f0ef | ||
|
|
f30040f359 | ||
|
|
052f1ac301 | ||
|
|
14813e1993 | ||
|
|
38d334251a | ||
|
|
5f518d19f3 | ||
|
|
1a2995d184 | ||
|
|
408d9ae62f | ||
|
|
11624bfbc5 | ||
|
|
a80d2a617f | ||
|
|
8a8790ec76 | ||
|
|
7d9ddf4dea | ||
|
|
601ac6a2e1 | ||
|
|
f4f391fb13 | ||
|
|
5ccd056cde | ||
|
|
33503a28fc | ||
|
|
5a8bc496f3 | ||
|
|
85ba03dc59 | ||
|
|
2873aab522 | ||
|
|
1a8114fe68 | ||
|
|
9b62f90efb | ||
|
|
a15464d431 | ||
|
|
459e0e8b86 | ||
|
|
01ecec9731 | ||
|
|
461f98a8ed | ||
|
|
067f0ea208 | ||
|
|
ed059604ef | ||
|
|
a29cb75a8e | ||
|
|
276e15d889 | ||
|
|
8abbe2dfc0 | ||
|
|
aeb84f69fc | ||
|
|
4d42a83912 | ||
|
|
f4dd2d68ee | ||
|
|
374695c6ae | ||
|
|
4cfcd228ad | ||
|
|
a2234c0bee | ||
|
|
d187d2073d | ||
|
|
00ab65e12a | ||
|
|
8faf6625e7 | ||
|
|
0fa9934f93 | ||
|
|
8ea6cdcf34 | ||
|
|
c084eea157 | ||
|
|
2180f6a60e | ||
|
|
e5f3b34d18 | ||
|
|
52cfef2afd | ||
|
|
4d14e5edb1 | ||
|
|
50742a761e | ||
|
|
97998cf761 | ||
|
|
a7a3820298 | ||
|
|
0b39902ed5 | ||
|
|
2344dee5d2 | ||
|
|
50c6951b37 | ||
|
|
84b2e1da25 | ||
|
|
778ecd4d97 | ||
|
|
31058a0661 | ||
|
|
19be76e590 | ||
|
|
26b979efc9 | ||
|
|
99a6d33c3e | ||
|
|
3b21ebb72e | ||
|
|
61cf584a93 | ||
|
|
3f27fea41f | ||
|
|
209524648c | ||
|
|
478906e9ba | ||
|
|
b64f53b840 | ||
|
|
98f00969a8 | ||
|
|
543124d254 | ||
|
|
31a480cf97 | ||
|
|
9dda862a1f | ||
|
|
274a8f46eb | ||
|
|
2a67ea7782 | ||
|
|
32f9116025 | ||
|
|
007ada9840 | ||
|
|
8eff466afa | ||
|
|
956bd5eca6 | ||
|
|
f3e709460f | ||
|
|
82078d75d5 | ||
|
|
3f18c0b575 | ||
|
|
51e8d8254d | ||
|
|
a37ea5af90 | ||
|
|
0a6d3fe874 | ||
|
|
c92478e3f3 | ||
|
|
c21791af74 | ||
|
|
1ffb49205c | ||
|
|
0a68963701 | ||
|
|
dc29a6793b | ||
|
|
d3c26b3dea | ||
|
|
fcf53cf71a | ||
|
|
5a872d7f37 | ||
|
|
eaa38ecd66 | ||
|
|
aeadafd7b1 | ||
|
|
8c09fb03b6 | ||
|
|
e3d3d0d3a4 | ||
|
|
81af357a85 | ||
|
|
451bf8836e | ||
|
|
ec7788f963 | ||
|
|
612590da3b | ||
|
|
c967d12610 | ||
|
|
9cfb873788 | ||
|
|
b482cd9451 | ||
|
|
e9144e2ad3 | ||
|
|
6157737c56 | ||
|
|
7fd7731210 | ||
|
|
061092e700 | ||
|
|
62ed40f4b7 | ||
|
|
5ee41f6476 | ||
|
|
94f9e0f047 | ||
|
|
97ab719c98 | ||
|
|
8d75a80ac6 | ||
|
|
8529b1de13 | ||
|
|
893c0d8730 | ||
|
|
746b8cf090 | ||
|
|
3716709a9b | ||
|
|
99a5ea33d1 | ||
|
|
accab50355 | ||
|
|
dfd44bbf2b | ||
|
|
5a6e2e2e7f | ||
|
|
6e2594977e | ||
|
|
f23e4efcc8 | ||
|
|
ea053f46b3 | ||
|
|
23273aed80 | ||
|
|
d5d27dceb9 | ||
|
|
4448ca8703 | ||
|
|
ee3caad3a2 | ||
|
|
78957f049a | ||
|
|
e6de758c33 | ||
|
|
08d6447046 | ||
|
|
5477a3996f | ||
|
|
c01d988b21 | ||
|
|
6d3ae4faa3 | ||
|
|
b817035e39 | ||
|
|
16f9e23465 | ||
|
|
f6d0f8dcb1 | ||
|
|
d86ab7c62a | ||
|
|
d938690740 | ||
|
|
2521b9c37d | ||
|
|
5e424d4f77 | ||
|
|
f596833a30 | ||
|
|
7b1338c580 | ||
|
|
ca69919c26 | ||
|
|
18b4e52aab | ||
|
|
e0ba72c033 | ||
|
|
f8c48784ad | ||
|
|
6bc8bb2836 | ||
|
|
800003347b | ||
|
|
f9408070fe | ||
|
|
b5db71661a | ||
|
|
3280a30614 | ||
|
|
88730c6f75 | ||
|
|
56377c00b2 | ||
|
|
14c7b9e8e0 | ||
|
|
77ac72d7e5 | ||
|
|
a796994c2e | ||
|
|
837c2f4d6b | ||
|
|
90037ded9d | ||
|
|
31a9210162 | ||
|
|
2b2d09bfcc | ||
|
|
dc9fd09c2f | ||
|
|
36a89a3ae6 | ||
|
|
8e753d7a30 | ||
|
|
91990f5ef2 | ||
|
|
b6408e9295 | ||
|
|
d72c9a2336 | ||
|
|
64fc122760 | ||
|
|
dea1eeed59 | ||
|
|
66e101a33a | ||
|
|
c609c701e7 | ||
|
|
b40f82dc9b | ||
|
|
324d94d035 | ||
|
|
40569c8c71 | ||
|
|
dae792cc35 | ||
|
|
f1c3c93064 | ||
|
|
4db10f1e5a | ||
|
|
42aa88fabd | ||
|
|
f8cfdf6ab6 | ||
|
|
bb002c70dc | ||
|
|
46232e3f1e | ||
|
|
978f355dcf | ||
|
|
f2f973b157 | ||
|
|
48567464fc | ||
|
|
ee4731cb09 | ||
|
|
3dc2620589 | ||
|
|
d8dca59255 | ||
|
|
6c984cc2d7 | ||
|
|
70553a1aaa | ||
|
|
a787cb748c | ||
|
|
cc0ed4762a | ||
|
|
597064a18f | ||
|
|
3ce06e1cac | ||
|
|
1e818bb3de | ||
|
|
9e0d116af8 | ||
|
|
9ac7ae1330 | ||
|
|
481f1d853e | ||
|
|
833f6282b5 | ||
|
|
2019fca31d | ||
|
|
6057c8a437 | ||
|
|
0282138e58 | ||
|
|
57ed526b22 | ||
|
|
4ac667b336 | ||
|
|
91657a924a | ||
|
|
0a00993580 | ||
|
|
bedc3f579a | ||
|
|
20dadfb75f | ||
|
|
a9ad8c783c | ||
|
|
fb91088a7e | ||
|
|
a5b84b9d0f | ||
|
|
5ce675c5b3 | ||
|
|
aa7ce82940 | ||
|
|
5dfa5ee4c6 | ||
|
|
77b80265ac | ||
|
|
49bfae9d3d | ||
|
|
6b3a102051 | ||
|
|
bfb85aa8e5 | ||
|
|
780b0f87b8 | ||
|
|
5ddd3202a2 | ||
|
|
59f7310356 | ||
|
|
73624be3f2 | ||
|
|
4fd65f7beb | ||
|
|
ed8105a604 | ||
|
|
a363ceb5ac | ||
|
|
947d5f151b | ||
|
|
ff0b800527 | ||
|
|
f610662539 | ||
|
|
9acb8788f3 | ||
|
|
f5461c6d33 | ||
|
|
0c0640bda8 | ||
|
|
473bb25455 | ||
|
|
c4d07556a5 | ||
|
|
879e2d4063 | ||
|
|
726502b446 | ||
|
|
e193769b36 | ||
|
|
4cd3455591 | ||
|
|
db1fe400f8 | ||
|
|
95ab2ed7ea | ||
|
|
4e49179d0a | ||
|
|
97f6c2f83b | ||
|
|
d86f2a5502 | ||
|
|
b23601527d | ||
|
|
b766caf185 | ||
|
|
8a15590907 | ||
|
|
da485e7ac9 | ||
|
|
7d3a4b15da | ||
|
|
2baa17b31b | ||
|
|
8a5692642b | ||
|
|
3336c95791 | ||
|
|
7db2e3630e | ||
|
|
61f06f8232 | ||
|
|
6ce6267133 | ||
|
|
21189ca797 | ||
|
|
353c6f6276 | ||
|
|
b88329d583 | ||
|
|
67d279c858 | ||
|
|
c3d7126380 | ||
|
|
b777dadd52 | ||
|
|
4fc75e09f5 | ||
|
|
45f39f92dc | ||
|
|
260a008c42 | ||
|
|
09ffe60e38 | ||
|
|
4a2e438102 | ||
|
|
0c34d0a385 | ||
|
|
9c18709c27 | ||
|
|
af14e89640 | ||
|
|
ec830c6ad8 | ||
|
|
e9bff70fde | ||
|
|
c168533065 | ||
|
|
645fef54bb | ||
|
|
1210b1841a | ||
|
|
d09eb1ea5a | ||
|
|
1400f2e7f7 | ||
|
|
bc3f07288a | ||
|
|
3aa3ccf337 | ||
|
|
a791130bcf | ||
|
|
2c73dd5d76 | ||
|
|
b7448b0b89 | ||
|
|
dd3b48836b | ||
|
|
7e240e1be0 | ||
|
|
1ed0fa8f0e | ||
|
|
bfcd4cb0db | ||
|
|
02288b3e4d | ||
|
|
f989ba8b99 | ||
|
|
845ee4ac61 | ||
|
|
66f9df4ff5 | ||
|
|
92f1586200 | ||
|
|
bae1ef1292 | ||
|
|
af95ace5dd | ||
|
|
3e74aafb95 | ||
|
|
a1d0b23ad4 | ||
|
|
e866b3dcb3 | ||
|
|
7dac8c1272 | ||
|
|
048e423b03 | ||
|
|
ae5c5db10e | ||
|
|
d9aadf1115 | ||
|
|
8fbe31d0fe | ||
|
|
1b9bd8e010 | ||
|
|
ab4aecdae9 | ||
|
|
b30d4aab68 | ||
|
|
9695207702 | ||
|
|
28bcb5e507 | ||
|
|
ea88fe4d11 | ||
|
|
b082102b20 | ||
|
|
2d817c3b79 | ||
|
|
aee84806bf | ||
|
|
6b7d1002d0 | ||
|
|
cc3662a76f | ||
|
|
25fb1ecde4 | ||
|
|
022299de23 | ||
|
|
f736445b3a | ||
|
|
0326654d8b | ||
|
|
80869ed818 | ||
|
|
9b41a81057 | ||
|
|
0d75cc08a0 | ||
|
|
5f7a91d797 | ||
|
|
bc5657c88d | ||
|
|
844a2295d7 | ||
|
|
f7184bf453 | ||
|
|
e926711645 | ||
|
|
2a489c43f3 | ||
|
|
93cf774cfd |
8
.babelrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-runtime", {
|
||||
"regenerator": true
|
||||
}]
|
||||
]
|
||||
}
|
||||
4
.gitignore
vendored
@ -3,13 +3,15 @@
|
||||
.DS_Store?
|
||||
._*
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
nbproject/
|
||||
.idea/
|
||||
.git/
|
||||
.vscode
|
||||
/.project
|
||||
*.log
|
||||
|
||||
/node_modules/
|
||||
*.js.ignore
|
||||
|
||||
|
||||
55
README.md
@ -1,13 +1,11 @@
|
||||
# miniPaint
|
||||
|
||||
Online graphics editing tool lets create, edit images using HTML5 technologies.
|
||||
No need to buy, download, install or have obsolete flash.
|
||||
Key features: layers, drag & drop, transparency, filters, no-flash, open source.
|
||||
Online image editor lets you create and edit images using HTML5 technologies. No need to buy, download, install, or have outdated flash. No ads. Key features: layers, filters, open source Photoshop alternative.
|
||||
|
||||
miniPaint operates directly in the browser. You can create images, paste from clipboard (ctrl+v) or upload from computer (using menu or drag & drop). Nothing will be sent to any server. Everything stays in your browser.
|
||||
miniPaint operates directly in the browser. You can create images by pasting from the clipboard (ctrl+v) or uploading from the computer (_using menu or drag & drop_). Nothing will be sent to any server. Everything stays in your browser.
|
||||
|
||||
## URL:
|
||||
**http://viliusle.github.io/miniPaint/**
|
||||
**https://viliusle.github.io/miniPaint/**
|
||||
|
||||
## Preview:
|
||||

|
||||
@ -16,42 +14,47 @@ miniPaint operates directly in the browser. You can create images, paste from cl
|
||||
**Change log:** [/miniPaint/releases](https://github.com/viliusle/miniPaint/releases)
|
||||
|
||||
## Browser Support
|
||||
- Firefox
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Opera
|
||||
- Edge
|
||||
- Safari
|
||||
- IE 11 (?)
|
||||
- Yandex
|
||||
|
||||
## Features
|
||||
|
||||
- **Files**: open images, directories, URL, drag and drop, save (PNG, JPG, BMP, WEBP, animated GIF, JSON (layers data), print.
|
||||
- **Edit**: Undo, cut, copy, paste, selection, paste from clipboard.
|
||||
- **Image**: information, EXIF, trim, zoom, resize (Hermite resample, default resize), rotate, flip, color corrections (brightness, contrast, hue, saturation, luminance), auto adjust colors, grid, histogram, negative.
|
||||
- **Layers**: multiple layers system, differences, merge, flatten, Transparency support.
|
||||
- **Effects**: Black and White, Blur (box, Gaussian, stack, zoom), Bulge/Pinch, Denoise, Desaturate, Dither, Dot Screen, Edge, Emboss, Enrich, Gamma, Grains, GrayScale, Heatmap, JPG Compression, Mosaic, Oil, Sepia, Sharpen, Solarize, Tilt Shift, Vignette, Vibrance, Vintage,
|
||||
- **Tools**: pencil, brush, magic wand, erase, fill, color picker, letters, crop, blur, sharpen, desaturate, clone, borders, sprites, key-points, color to alpha, color zoom, replace color, restore alpha, content fill.
|
||||
- **Help**: keyboard shortcuts, translations.
|
||||
**Files**: open images, directories, URLs, data URLs, drag and drop, save (PNG, JPG, BMP, WEBP, animated GIF, TIFF, JSON (layers data), print.
|
||||
|
||||
### Embed
|
||||
**Edit**: undo, cut, copy, paste, selection, paste from the clipboard.
|
||||
|
||||
To embed this app in other page, use this HTML code:
|
||||
**Image**: information, EXIF, trim, zoom, resize (Hermite resample, default resize), rotate, flip, color corrections (brightness, contrast, hue, saturation, luminance), automatic color adjustment, grid, histogram, negative.
|
||||
|
||||
<iframe style="width:100%; height:35vw;" src="https://viliusle.github.io/miniPaint/"></iframe>
|
||||
**Layers**: multi-layer system, differences, merging, flattening, transparency support.
|
||||
|
||||
**Effects**: black and white, blur (box, gaussian, stack, zoom), bulge/pinch, denoise, desaturation, dither, dot screen, edge, emboss, enrich, gamma, grains, grayscale, heatmap, jpg compression, mosaic, oil, sepia, sharpen, solarize, tilt shift, vignette, vibrance, vintage, blueprint, night vision, pencil, also instagram filters: 1977, aden, clarendon, gingham, inkwell, lo-fi, toaster, valencia, x-pro ii.
|
||||
|
||||
**Tools**: pencil, brush, magic wand, eraser, fill, color picker, letter, crop, blur, sharpener, desaturation, clone, borders, sprites, keypoints, color zoom, change color, restore transparency, content fill.
|
||||
|
||||
**Help**: keyboard shortcuts, translation.
|
||||
|
||||
## Embed
|
||||
To embed this app on another page, use the following HTML code:
|
||||
|
||||
<iframe style="box-sizing:border-box; width:100%; height:100vh;" id="miniPaint" src="https://viliusle.github.io/miniPaint/" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
|
||||
## Build instructions
|
||||
See [Wiki > Build instructions](https://github.com/viliusle/miniPaint/wiki/Build-instructions)
|
||||
|
||||
- git clone https://github.com/viliusle/miniPaint.git
|
||||
- cd [miniPaint directory]
|
||||
- npm install
|
||||
- webpack-dev-server (using http://localhost:8080/ with live reload, require: npm install -g webpack-dev-server)
|
||||
- edit files...
|
||||
- webpack -p (build for production)
|
||||
## Wiki
|
||||
See [Wiki](https://github.com/viliusle/miniPaint/wiki)
|
||||
|
||||
### License
|
||||
## Contributors
|
||||
<a align="center" href="https://github.com/viliusle/miniPaint/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=viliusle/miniPaint" />
|
||||
</a>
|
||||
|
||||
## License
|
||||
MIT License
|
||||
|
||||
## Support
|
||||
|
||||
Please use the GitHub issues for support, features, issues or use mail www.viliusl@gmail.com for contacts.
|
||||
Please use the GitHub issues for support, feature requests and bug reports, or contact us by sending an email to www.viliusl@gmail.com.
|
||||
|
||||
15
SECURITY.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| latest | :white_check_mark: |
|
||||
| < latest | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please send details to www.viliusl@gmail.com
|
||||
63
dist/bundle.js
vendored
47
dist/bundle.js.LICENSE.txt
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
||||
pica
|
||||
https://github.com/nodeca/pica
|
||||
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Block below copied from Protovis: http://mbostock.github.com/protovis/
|
||||
* Copyright 2010 Stanford Visualization Group
|
||||
* Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
|
||||
* @license
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.7.1
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2023-08-28T13:37Z
|
||||
*/
|
||||
|
||||
/*!
|
||||
* quantize.js Copyright 2008 Nick Rabinowitz.
|
||||
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
* @license
|
||||
*/
|
||||
|
||||
/*! alertifyjs - v1.13.1 - Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com) */
|
||||
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/**
|
||||
* hermite-resize - Canvas image resize/resample using Hermite filter with JavaScript.
|
||||
* @version v2.2.10
|
||||
* @link https://github.com/viliusle/miniPaint
|
||||
* @license MIT
|
||||
*/
|
||||
2
dist/bundle.js.map
vendored
@ -1 +1 @@
|
||||
{"version":3,"file":"dist/bundle.js","sources":["webpack:///dist/bundle.js"],"mappings":"AAAA;AAwsCA;;;;;;;;;;;;;AAqjJA;;;;;;;;;;AAuhBA;;;;;;;;;;;;;;;;;;AA8xyBA;;;;;;;;;;;AAyKA;;;;;;AA2uBA","sourceRoot":""}
|
||||
{"version":3,"file":"bundle.js","sources":["webpack://miniPaint/bundle.js"],"mappings":";AAAA","sourceRoot":""}
|
||||
76
examples/add-edit-imgData.html
Normal file
@ -0,0 +1,76 @@
|
||||
<html>
|
||||
<body style="margin:0;">
|
||||
|
||||
<iframe id="myFrame" style="width:100%;height:100vh;border:0;" src="../" allow="camera"></iframe>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function (e) {
|
||||
draw_various();
|
||||
}, false);
|
||||
|
||||
async function draw_various() {
|
||||
var Layers = document.getElementById('myFrame').contentWindow.Layers;
|
||||
|
||||
//add layer
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 50;
|
||||
canvas.height = 50;
|
||||
var ctx = canvas.getContext("2d");
|
||||
cross_X(ctx, 25, 25);
|
||||
var params = {
|
||||
type: 'image',
|
||||
data: canvas.toDataURL("image/png"),
|
||||
x: 50,
|
||||
y: 50,
|
||||
width: canvas.width,
|
||||
height: canvas.height,
|
||||
};
|
||||
await Layers.insert(params);
|
||||
|
||||
//add new layer
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 400;
|
||||
canvas.height = 400;
|
||||
var ctx = canvas.getContext("2d");
|
||||
cross_X(ctx, 200, 200, null, '#00cc00');
|
||||
var params = {
|
||||
type: 'image',
|
||||
data: canvas.toDataURL("image/png"),
|
||||
width: canvas.width,
|
||||
height: canvas.height,
|
||||
};
|
||||
await Layers.insert(params);
|
||||
|
||||
//update last layer
|
||||
var canvas = Layers.convert_layer_to_canvas(null, true); //no trim
|
||||
var ctx = canvas.getContext("2d");
|
||||
cross_X(ctx, 300, 300, null, '#00cc00');
|
||||
Layers.update_layer_image(canvas);
|
||||
//also update layer
|
||||
var link = Layers.get_layer();
|
||||
link.x = parseInt(canvas.dataset.x);
|
||||
link.y = parseInt(canvas.dataset.y);
|
||||
link.width = canvas.width;
|
||||
link.height = canvas.height;
|
||||
}
|
||||
|
||||
function cross_X(ctx, x, y, size = 20, col = '#ff0000') {
|
||||
if(size == null)
|
||||
size = 20;
|
||||
x = parseFloat(x);
|
||||
y = parseFloat(y);
|
||||
size = parseInt(size);
|
||||
var lw = parseInt(5);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x - size, y - size);
|
||||
ctx.lineTo(x + size, y + size);
|
||||
ctx.lineWidth = lw;
|
||||
ctx.strokeStyle = col;
|
||||
ctx.stroke();
|
||||
ctx.moveTo(x + size, y - size);
|
||||
ctx.lineTo(x - size, y + size);
|
||||
ctx.lineWidth = lw;
|
||||
ctx.strokeStyle = col;
|
||||
ctx.stroke();
|
||||
}
|
||||
</script>
|
||||
@ -1,16 +1,23 @@
|
||||
<html>
|
||||
<body style="margin:0;">
|
||||
|
||||
<iframe id="myFrame" style="width:100%;height:70vh;" src="../"></iframe>
|
||||
<iframe id="myFrame" style="width:100%;height:70vh;border:0;" src="../" allow="camera"></iframe>
|
||||
|
||||
<div style="height:20vh;margin:10px;">
|
||||
Click on image to edit.
|
||||
<br /><br />
|
||||
<button onclick="my_update()">Update</button>
|
||||
<button onclick="my_save()">Save</button>
|
||||
<button onclick="open_image()">Open image</button>
|
||||
<button onclick="update_image()">Update image</button>
|
||||
<button onclick="save_image()">Save image</button>
|
||||
OR
|
||||
<button onclick="open_json()">Open JSON</button>
|
||||
<button onclick="save_json()">Save JSON</button>
|
||||
<br /><br />
|
||||
|
||||
<img style="max-height:100%" id="testImage" alt="" src="../images/logo.png" onclick="open_image(this)" />
|
||||
<img style="max-height:100%" id="testImage" alt="" src="../images/logo-colors.png" onclick="open_image(this)" />
|
||||
|
||||
<textarea rows="8" style="width:500px;" id="testJson"></textarea>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -20,6 +27,8 @@
|
||||
* @param {string|image} image image or image id
|
||||
*/
|
||||
function open_image(image){
|
||||
if(image == undefined)
|
||||
image = document.getElementById('testImage');
|
||||
if(typeof image == 'string'){
|
||||
image = document.getElementById(image);
|
||||
}
|
||||
@ -37,7 +46,20 @@ function open_image(image){
|
||||
Layers.insert(new_layer);
|
||||
}
|
||||
|
||||
function my_save(){
|
||||
function open_json(){
|
||||
var miniPaint = document.getElementById('myFrame').contentWindow;
|
||||
var miniPaint_FileOpen = miniPaint.FileOpen;
|
||||
|
||||
window.fetch("../images/test-collection.json").then(function(response) {
|
||||
return response.json();
|
||||
}).then(function(json) {
|
||||
miniPaint_FileOpen.load_json(json, false);
|
||||
}).catch(function(ex) {
|
||||
alert('Sorry, image could not be loaded.');
|
||||
});
|
||||
}
|
||||
|
||||
function save_image(){
|
||||
var Layers = document.getElementById('myFrame').contentWindow.Layers;
|
||||
var tempCanvas = document.createElement("canvas");
|
||||
var tempCtx = tempCanvas.getContext("2d");
|
||||
@ -45,14 +67,32 @@ function my_save(){
|
||||
tempCanvas.width = dim.width;
|
||||
tempCanvas.height = dim.height;
|
||||
Layers.convert_layers_to_canvas(tempCtx);
|
||||
tempCanvas.toBlob(function(blob) {
|
||||
//image data here
|
||||
alert('Data length: ' + blob.size);
|
||||
console.log(blob);
|
||||
});
|
||||
|
||||
if(is_edge_or_ie() == false){
|
||||
//update image using blob (faster)
|
||||
tempCanvas.toBlob(function (blob) {
|
||||
alert('Data length: ' + blob.size);
|
||||
console.log(blob);
|
||||
}, 'image/png');
|
||||
}
|
||||
else{
|
||||
//slow way for IE, Edge
|
||||
var data = tempCanvas.toDataURL();
|
||||
alert('Data length: ' + data.length);
|
||||
console.log(data);
|
||||
}
|
||||
}
|
||||
|
||||
function my_update(){
|
||||
function save_json(){
|
||||
var miniPaint = document.getElementById('myFrame').contentWindow;
|
||||
var miniPaint_FileSave = miniPaint.FileSave;
|
||||
|
||||
var data_json = miniPaint_FileSave.export_as_json();
|
||||
|
||||
document.getElementById('testJson').value = data_json;
|
||||
}
|
||||
|
||||
function update_image(){
|
||||
var target = document.getElementById('testImage');
|
||||
|
||||
var Layers = document.getElementById('myFrame').contentWindow.Layers;
|
||||
@ -67,4 +107,22 @@ function my_update(){
|
||||
target.height = dim.height;
|
||||
target.src = tempCanvas.toDataURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* will auto load image on page load. Uncomment line below to make it work
|
||||
*/
|
||||
window.onload = function () {
|
||||
//open_image(document.getElementById('testImage')); //uncomment me
|
||||
};
|
||||
|
||||
//if IE 11 or Edge
|
||||
function is_edge_or_ie() {
|
||||
//ie11
|
||||
if( !(window.ActiveXObject) && "ActiveXObject" in window )
|
||||
return true;
|
||||
//edge
|
||||
if( navigator.userAgent.indexOf('Edge/') != -1 )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
71
examples/zoom.html
Normal file
@ -0,0 +1,71 @@
|
||||
<html>
|
||||
<body style="margin:0;">
|
||||
|
||||
<iframe id="myFrame" style="width:100%;height:100vh;border:0;" src="../" allow="camera"></iframe>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function (e) {
|
||||
main();
|
||||
}, false);
|
||||
|
||||
async function main() {
|
||||
var Layers = document.getElementById('myFrame').contentWindow.Layers;
|
||||
var config = document.getElementById('myFrame').contentWindow.AppConfig;
|
||||
|
||||
var canvas_width = 800;
|
||||
var canvas_height = 600;
|
||||
|
||||
//set size
|
||||
Layers.Base_gui.set_size(canvas_width, canvas_height);
|
||||
|
||||
//add rectangle
|
||||
this.layer = {
|
||||
name: 'layer1',
|
||||
type: 'rectangle',
|
||||
params: {
|
||||
fill: true,
|
||||
square: false,
|
||||
border_size: 2,
|
||||
border: false,
|
||||
border_color: "#1b1bd8",
|
||||
fill_color: "#1b1bd8"
|
||||
},
|
||||
color: '#ff0000',
|
||||
render_function: ['rectangle', 'render'],
|
||||
x: canvas_width/2 - 25,
|
||||
y: canvas_height/2 - 25,
|
||||
width: 50,
|
||||
height: 50,
|
||||
};
|
||||
await Layers.insert(this.layer);
|
||||
|
||||
//zoom to 500%
|
||||
setTimeout(function () {
|
||||
Layers.Base_gui.GUI_preview.zoom_to_position(0, 0);
|
||||
Layers.Base_gui.GUI_preview.zoom(500);
|
||||
}, 100);
|
||||
|
||||
//do this after system changed zoom position
|
||||
setTimeout(function () {
|
||||
//move visible area to begin of rectangle
|
||||
Layers.Base_gui.GUI_preview.zoom_to_position(500, 500); //change zoom position
|
||||
}, 500);
|
||||
|
||||
//action after 1 s - for preview purpose
|
||||
setTimeout(function () {
|
||||
//move visible area so rect is in center
|
||||
|
||||
var visible_area = Layers.Base_gui.get_visible_area_size();
|
||||
|
||||
//center of rect
|
||||
var cx = canvas_width/2;
|
||||
var cy = canvas_height/2;
|
||||
|
||||
//calc needed coords
|
||||
var x = cx - visible_area.width / 2;
|
||||
var y = cy - visible_area.height / 2;
|
||||
|
||||
Layers.Base_gui.GUI_preview.zoom_to_position(x, y); //change zoom position
|
||||
}, 1000);
|
||||
}
|
||||
</script>
|
||||
|
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 4.5 KiB |
13
images/favicon.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 298.73 298.73" style="enable-background:new 0 0 298.73 298.73;" xml:space="preserve">
|
||||
<g>
|
||||
<path style="fill:#010002;" d="M264.959,9.35H33.787C15.153,9.35,0,24.498,0,43.154v212.461c0,18.634,15.153,33.766,33.787,33.766
|
||||
h231.171c18.634,0,33.771-15.132,33.771-33.766V43.154C298.73,24.498,283.593,9.35,264.959,9.35z M193.174,59.623
|
||||
c18.02,0,32.634,14.615,32.634,32.634s-14.615,32.634-32.634,32.634c-18.025,0-32.634-14.615-32.634-32.634
|
||||
S175.149,59.623,193.174,59.623z M254.363,258.149H149.362H49.039c-9.013,0-13.027-6.521-8.964-14.566l56.006-110.93
|
||||
c4.058-8.044,11.792-8.762,17.269-1.605l56.316,73.596c5.477,7.158,15.05,7.767,21.386,1.354l13.777-13.951
|
||||
c6.331-6.413,15.659-5.619,20.826,1.762l35.675,50.959C266.487,252.16,263.376,258.149,254.363,258.149z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
13
images/icons/animation.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 30.051 30.051" style="enable-background:new 0 0 30.051 30.051;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M19.982,14.438l-6.24-4.536c-0.229-0.166-0.533-0.191-0.784-0.062c-0.253,0.128-0.411,0.388-0.411,0.669v9.069
|
||||
c0,0.284,0.158,0.543,0.411,0.671c0.107,0.054,0.224,0.081,0.342,0.081c0.154,0,0.31-0.049,0.442-0.146l6.24-4.532
|
||||
c0.197-0.145,0.312-0.369,0.312-0.607C20.295,14.803,20.177,14.58,19.982,14.438z"/>
|
||||
<path d="M15.026,0.002C6.726,0.002,0,6.728,0,15.028c0,8.297,6.726,15.021,15.026,15.021c8.298,0,15.025-6.725,15.025-15.021
|
||||
C30.052,6.728,23.324,0.002,15.026,0.002z M15.026,27.542c-6.912,0-12.516-5.601-12.516-12.514c0-6.91,5.604-12.518,12.516-12.518
|
||||
c6.911,0,12.514,5.607,12.514,12.518C27.541,21.941,21.937,27.542,15.026,27.542z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
5
images/icons/arrow-down.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="124" height="150" viewBox="0 0 124 150" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="55" y="14" width="14" height="63"/>
|
||||
<rect x="116" width="14" height="61" transform="rotate(90 116 0)"/>
|
||||
<path d="M62 150L8.30643 75L115.694 75L62 150Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 258 B |
28
images/icons/blur.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M264.574,4.675C262.697,1.761,259.467,0,256,0c-3.467,0-6.697,1.761-8.574,4.675
|
||||
c-6.532,10.14-159.966,249.362-159.966,338.784C87.459,436.393,163.066,512,256,512s168.541-75.607,168.541-168.541
|
||||
C424.541,254.037,271.106,14.815,264.574,4.675z M256,491.602c-81.686,0-148.142-66.456-148.142-148.143
|
||||
c0-34.037,26.926-101.269,77.865-194.427C213.83,97.626,242.219,51.324,256,29.29c13.77,22.016,42.123,68.259,70.223,119.64
|
||||
c50.976,93.212,77.92,160.478,77.92,194.529C404.142,425.146,337.686,491.602,256,491.602z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M375.907,332.939c-5.633,0-10.199,4.566-10.199,10.199c0,43.197-25.482,82.521-64.919,100.181
|
||||
c-5.141,2.301-7.442,8.335-5.14,13.476c1.695,3.788,5.416,6.034,9.314,6.034c1.393,0,2.809-0.287,4.163-0.893
|
||||
c46.764-20.941,76.981-67.572,76.981-118.797C386.106,337.505,381.54,332.939,375.907,332.939z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M281.818,460.702c-0.729-5.586-5.85-9.519-11.435-8.791c-4.736,0.619-9.574,0.933-14.383,0.933
|
||||
c-5.633,0-10.199,4.566-10.199,10.199c0,5.633,4.566,10.199,10.199,10.199c5.69,0,11.419-0.372,17.028-1.106
|
||||
C278.613,471.407,282.548,466.287,281.818,460.702z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
4
images/icons/bold.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.21 13c2.106 0 3.412-1.087 3.412-2.823 0-1.306-.984-2.283-2.324-2.386v-.055a2.176 2.176 0 0 0 1.852-2.14c0-1.51-1.162-2.46-3.014-2.46H3.843V13H8.21zM5.908 4.674h1.696c.963 0 1.517.451 1.517 1.244 0 .834-.629 1.32-1.73 1.32H5.908V4.673zm0 6.788V8.598h1.73c1.217 0 1.88.492 1.88 1.415 0 .943-.643 1.449-1.832 1.449H5.907z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 491 B |
1
images/icons/brush.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="443pt" viewBox="0 0 443.06138 443" width="443pt" xmlns="http://www.w3.org/2000/svg"><path d="m431.328125 25.894531-14.136719-14.136719c-8.070312-8.078124-19.210937-12.320312-30.613281-11.6601558-11.402344.6601558-21.976563 6.1640628-29.058594 15.1249998l-117.023437 164.839844c-4.089844 5.761719-10.511719 9.425781-17.554688 10.019531-7.039062.59375-13.984375-1.945312-18.980468-6.941406l-34.234376-34.207031c-9.480468-9.109375-24.46875-9.109375-33.949218 0l-11.296875 11.304687 158.398437 158.398438 11.304688-11.304688c4.527344-4.488281 7.070312-10.597656 7.070312-16.96875 0-6.375-2.542968-12.484375-7.070312-16.972656l-34.222656-34.234375c-4.996094-4.996094-7.535157-11.941406-6.941407-18.980469.59375-7.042969 4.257813-13.464843 10.019531-17.554687l165-117.183594c8.890626-7.109375 14.332032-17.671875 14.960938-29.035156.628906-11.367188-3.617188-22.464844-11.671875-30.507813zm-24 43.808594c-9.375 9.371094-24.570313 9.371094-33.945313 0-9.371093-9.375-9.371093-24.574219 0-33.945313 9.496094-9.0625 24.441407-9.0625 33.9375 0 9.375 9.371094 9.378907 24.570313.007813 33.945313zm0 0"/><path d="m390.351562 44.734375c-3.234374 0-6.152343 1.949219-7.390624 4.9375-1.234376 2.988281-.550782 6.429687 1.734374 8.71875 3.160157 3.03125 8.148438 3.03125 11.304688 0 2.289062-2.289063 2.972656-5.730469 1.734375-8.71875s-4.15625-4.9375-7.390625-4.9375zm0 0"/><path d="m135.792969 420.429688 22.65625 22.65625 113.085937-113.167969-158.398437-158.402344-113.136719 113.121094 22.65625 22.65625 84.847656-84.855469c2.007813-2.078125 4.984375-2.914062 7.78125-2.183594 2.796875.734375 4.980469 2.917969 5.710938 5.714844.734375 2.796875-.101563 5.773438-2.179688 7.78125l-84.847656 84.855469 22.632812 22.625 50.902344-50.90625c3.140625-3.03125 8.128906-2.988281 11.214844.097656s3.128906 8.078125.097656 11.214844l-50.90625 50.921875 22.617188 22.621094 62.214844-62.222657c3.125-3.125 8.191406-3.128906 11.316406-.003906 3.128906 3.125 3.128906 8.191406.003906 11.316406l-62.222656 62.222657 22.625 22.625 73.535156-73.535157c3.140625-3.03125 8.128906-2.988281 11.214844.097657 3.085937 3.085937 3.128906 8.074218.097656 11.214843zm0 0"/></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
17
images/icons/bulge_pinch.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 402.56 402.56" style="enable-background:new 0 0 402.56 402.56;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="38.613,234.88 38.4,274.56 96.64,274.56 116.693,265.173 9.6,372.48 39.68,402.56 147.2,295.253 137.813,316.587
|
||||
137.813,373.76 177.493,374.187 177.493,234.88 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="306.987,128.213 285.653,137.6 392.96,30.08 362.88,0 255.573,107.307 264.96,87.04 264.96,28.8 225.28,29.013
|
||||
225.28,167.893 364.587,167.893 364.16,128.213 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 778 B |
21
images/icons/clone.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 540.721 540.721" style="enable-background:new 0 0 540.721 540.721;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M521.858,465.271H18.862c-7.545,0-12.575,5.03-12.575,12.575v50.3c0,7.545,5.03,12.575,12.575,12.575h502.996
|
||||
c7.545,0,12.575-5.03,12.575-12.575v-50.3C534.433,470.301,529.403,465.271,521.858,465.271z"/>
|
||||
<path d="M227.606,98.084c5.03-5.03,20.12-12.575,30.18-12.575c7.545,0,12.575-5.03,12.575-12.575c0-7.545-5.03-10.06-12.575-10.06
|
||||
l0,0c-17.605,0-37.725,7.545-47.785,17.605c-12.575,10.06-22.635,27.665-22.635,47.785c0,7.545,5.03,10.06,12.575,10.06l0,0
|
||||
c7.545,0,12.575-2.515,12.575-10.06C212.516,118.204,220.061,103.114,227.606,98.084z"/>
|
||||
<path d="M18.862,440.121h502.996c5.03,0,7.545-2.515,10.06-5.03c2.515-2.515,2.515-7.545,0-12.575l-47.785-100.599
|
||||
c0-5.03-5.03-7.545-10.06-7.545H333.235v-77.964c25.15-20.12,60.359-60.36,60.359-110.659C393.594,55.33,338.265,0,270.36,0
|
||||
S147.126,57.845,147.126,125.749c-2.515,47.785,35.21,88.024,60.36,110.659v77.964H66.647c-5.03,0-10.06,2.515-10.06,7.545
|
||||
L8.802,422.517c-2.515,5.03-2.515,7.545,0,12.575C11.317,440.121,13.832,440.121,18.862,440.121z M169.761,125.749
|
||||
c0-55.33,45.27-100.599,98.084-100.599c52.815,0,98.084,45.27,98.084,100.599c0,37.725-27.665,75.449-55.33,93.054
|
||||
c-2.515,2.515-5.03,5.03-5.03,10.06v123.234c0,2.515-12.575,10.06-22.635,10.06h-37.725c-7.545,0-15.09-7.545-15.09-10.06V228.863
|
||||
c0-5.03-2.515-7.545-5.03-10.06C207.486,206.228,169.761,168.504,169.761,125.749z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
17
images/icons/crop.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="956.815px" height="956.815px" viewBox="0 0 956.815 956.815" style="enable-background:new 0 0 956.815 956.815;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path d="M137.621,162.622H20c-11.046,0-20,8.954-20,20v72.919c0,11.046,8.954,20,20,20h117.622L137.621,162.622L137.621,162.622z"
|
||||
/>
|
||||
<path d="M774.193,956.815c11.046,0,20-8.954,20-20V819.193H681.274v117.621c0,11.046,8.954,20,20,20L774.193,956.815
|
||||
L774.193,956.815z"/>
|
||||
<path d="M794.193,656.275V182.622c0-11.046-8.954-20-20-20H300.54v112.919h380.734v380.734H794.193z"/>
|
||||
<path d="M936.814,681.275H794.193H681.274H275.54V275.541V162.622V20c0-11.046-8.954-20-20-20h-72.918c-11.046,0-20,8.954-20,20
|
||||
v142.622v112.919v498.653c0,11.046,8.954,20,20,20h498.653h112.918h142.622c11.045,0,20-8.954,20-20v-72.918
|
||||
C956.814,690.229,947.86,681.275,936.814,681.275z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
6
images/icons/delete.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg height="365pt" viewBox="0 0 365.71733 365" width="365pt" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#f44336">
|
||||
<path d="m356.339844 296.347656-286.613282-286.613281c-12.5-12.5-32.765624-12.5-45.246093 0l-15.105469 15.082031c-12.5 12.503906-12.5 32.769532 0 45.25l286.613281 286.613282c12.503907 12.5 32.769531 12.5 45.25 0l15.082031-15.082032c12.523438-12.480468 12.523438-32.75.019532-45.25zm0 0"/>
|
||||
<path d="m295.988281 9.734375-286.613281 286.613281c-12.5 12.5-12.5 32.769532 0 45.25l15.082031 15.082032c12.503907 12.5 32.769531 12.5 45.25 0l286.632813-286.59375c12.503906-12.5 12.503906-32.765626 0-45.246094l-15.082032-15.082032c-12.5-12.523437-32.765624-12.523437-45.269531-.023437zm0 0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 719 B |
7
images/icons/desaturate.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)"><path d="M2646.5,3789.8c-1040.2-119.8-2106-953.5-2445-1917.3l-91.8-260.1L102,355.5c-5.1-1081-2.5-1279.9,33.1-1415c155.5-609.4,578.8-986.7,1282.4-1139.7c300.9-66.3,670.5-96.9,1534.8-127.5c400.3-12.7,831.2-43.3,961.2-63.7c464-76.5,836.3-229.5,1448.1-599.2c698.6-420.7,1063.2-550.7,1682.7-599.2c234.6-17.9,645,20.4,866.9,81.6c494.6,132.6,1007.1,476.8,1341.1,902.6c318.7,405.4,484.4,749.6,589,1223.8c53.5,255,56.1,313.6,58.6,1527.2c0,1155-5.1,1274.8-45.9,1415c-186.1,596.6-609.4,917.9-1374.2,1045.3c-135.1,22.9-550.7,51-963.7,63.7c-1560.3,53.5-1828,112.2-2957.5,662.9c-685.8,334-928,415.6-1328.3,458.9C2944.8,3820.4,2919.3,3820.4,2646.5,3789.8z M3378.2,3165.2c255-51,461.5-135.1,1014.7-413c543.1-270.3,821-382.4,1213.6-487c311-84.2,798-155.5,1042.8-155.5c142.8,0,158.1-5.1,234.6-91.8c112.2-124.9,214.2-163.2,420.7-163.2c193.8,0,359.5,61.2,423.2,153c40.8,56.1,48.5,58.6,328.9,43.3c894.9-51,1249.3-328.9,1246.7-971.4c0-117.3-7.6-247.3-17.8-288.1c-30.6-147.9-94.3-331.4-168.3-494.6l-76.5-168.3l-158.1-12.7c-379.9-30.6-563.4-270.3-372.2-487l73.9-86.7l-81.6-76.5c-211.6-198.9-527.8-359.5-843.9-428.3c-160.6-35.7-272.8-43.3-560.9-30.6c-555.8,20.4-777.6,99.4-1494,525.2C5111.9-174.8,4857-52.4,4482.2,70c-410.5,137.7-685.8,175.9-1402.3,206.5c-1287.5,51-1596,86.7-1891.8,219.3c-191.2,84.1-379.9,288.1-443.6,471.7c-66.3,193.8-58.6,471.7,17.9,696l61.2,175.9l155.5,5.1c226.9,5.1,402.8,119.8,433.4,280.5c20.4,107.1,0,168.3-84.1,249.9l-66.3,66.3l61.2,66.3c249.9,267.7,808.2,571.1,1200.8,657.8C2745.9,3213.6,3143.6,3213.6,3378.2,3165.2z M3391-391.5c221.8-112.2,397.7-351.8,362-492.1c-51-211.6-418.1-183.6-657.8,51C2972.8-712.8,2921.8-610.8,2932-496c5.1,79.1,22.9,102,96.9,137.7C3130.9-307.4,3240.5-317.6,3391-391.5z M1328.3-414.5c140.2-86.7,221.8-209.1,221.8-323.8c0-216.7-392.6-153-573.7,91.8C792.9-394.1,1040.2-230.9,1328.3-414.5z M5550.4-1273.7c135.1-84.1,244.8-257.5,221.8-349.3c-23-89.2-145.3-132.6-267.7-96.9c-137.7,43.4-293.2,163.2-341.7,267.7c-56.1,117.3-53.5,160.6,10.2,224.4C5244.5-1156.4,5387.3-1174.2,5550.4-1273.7z M2682.2-1339.9c293.2-165.7,341.6-476.8,73.9-476.8c-196.3,0-466.6,232-466.6,397.8C2289.5-1278.7,2503.7-1238,2682.2-1339.9z M6659.5-2446.5c209-107.1,372.2-308.5,372.2-461.5c0-68.8-79-150.4-163.2-173.4c-168.3-40.8-517.6,158.1-617,351.8C6111.3-2459.2,6353.6-2290.9,6659.5-2446.5z"/><path d="M3013.6,2639.9c-135.1-45.9-221.8-130-221.8-219.3c0-160.6,181-270.3,453.8-270.3c418.1-2.5,599.2,288.1,280.5,453.8C3408.8,2665.4,3138.5,2683.3,3013.6,2639.9z"/><path d="M2213,1490.1c-168.3-48.5-295.8-132.6-334-226.9c-28-68.8-25.5-89.2,17.9-168.3c188.7-351.9,1106.5-288.1,1106.5,79c0,48.5-22.9,114.7-51,150.4C2837.7,1472.2,2450.2,1556.4,2213,1490.1z"/><path d="M5693.2,1492.6c-119.8-40.8-216.7-145.3-216.7-232c0-267.7,594-372.2,846.5-147.9c201.4,181-17.9,410.5-387.5,407.9C5843.6,1520.7,5736.6,1507.9,5693.2,1492.6z"/><path d="M8051.6,1278.5c-124.9-53.5-178.5-109.6-178.5-188.7c0-137.7,165.7-229.5,415.6-229.5c175.9,0,341.7,73.9,377.3,168.3C8737.4,1227.5,8321.8,1395.8,8051.6,1278.5z"/><path d="M4321.5,1013.3c-147.9-28-234.6-102-234.6-204c0-124.9,96.9-186.1,313.6-198.9c204-12.7,346.7,35.7,392.6,132.6C4869.7,916.4,4609.6,1064.3,4321.5,1013.3z"/><path d="M6662.1,225.5c-196.3-48.4-344.2-181-344.2-311c0-323.8,775.1-453.8,1070.8-175.9C7671.7,3.7,7161.8,345.3,6662.1,225.5z"/></g></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
14
images/icons/erase.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="548.157px" height="548.157px" viewBox="0 0 548.157 548.157" style="enable-background:new 0 0 548.157 548.157;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path d="M545.027,112.765c-3.046-6.471-7.57-11.657-13.565-15.555c-5.996-3.9-12.614-5.852-19.846-5.852H292.351
|
||||
c-11.04,0-20.175,4.184-27.408,12.56L9.13,396.279c-4.758,5.328-7.661,11.56-8.708,18.698c-1.049,7.139-0.144,13.941,2.712,20.417
|
||||
c3.044,6.468,7.564,11.652,13.561,15.553c5.997,3.898,12.612,5.853,19.845,5.853h219.268c11.042,0,20.177-4.179,27.41-12.56
|
||||
l255.813-292.363c4.75-5.33,7.655-11.561,8.699-18.699C548.788,126.039,547.877,119.238,545.027,112.765z M255.811,420.254H36.54
|
||||
l95.93-109.632h219.27L255.811,420.254z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
images/icons/external.png
Normal file
|
After Width: | Height: | Size: 122 B |
19
images/icons/fill.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M494.412,245.154L371.59,122.507l93.792-93.934L437.07,0.304L343.28,94.237l-56.613-56.532L37.714,286.659
|
||||
l207.754,207.459c11.699,11.699,27.069,17.549,42.436,17.549c15.367,0,30.735-5.849,42.436-17.549l164.082-164.082
|
||||
c11.389-11.388,17.632-26.53,17.578-42.635C511.946,271.446,505.704,256.446,494.412,245.154z M466.131,301.745L302.048,465.828
|
||||
c-7.799,7.8-20.489,7.8-28.3-0.01L94.314,286.638L286.687,94.266l28.324,28.283L211.272,226.445l28.312,28.269L343.322,150.82
|
||||
l122.811,122.636c3.761,3.761,5.842,8.761,5.859,14.079C472.009,292.902,469.928,297.948,466.131,301.745z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M95.137,398.966c-10.179-15.198-20.245-27.482-20.669-27.997l-15.455-18.808l-15.455,18.808
|
||||
c-0.424,0.516-10.49,12.799-20.669,27.997C2.372,429.596,0,444.293,0,452.684c0,32.54,26.474,59.012,59.012,59.012
|
||||
c32.539,0,59.012-26.473,59.012-59.012C118.025,444.293,115.652,429.596,95.137,398.966z M59.012,471.688
|
||||
c-10.479,0-19.004-8.525-19.005-18.956c0.004-0.08,0.526-8.271,16.291-31.757c0.907-1.35,1.813-2.678,2.714-3.972
|
||||
c0.899,1.294,1.806,2.622,2.714,3.972c15.491,23.079,16.265,31.388,16.29,31.745C77.996,463.182,69.48,471.688,59.012,471.688z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
images/icons/gradient.png
Normal file
|
After Width: | Height: | Size: 265 B |
|
Before Width: | Height: | Size: 84 B After Width: | Height: | Size: 84 B |
2
images/icons/italic.svg
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-type-italic" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M7.991 11.674L9.53 4.455c.123-.595.246-.71 1.347-.807l.11-.52H7.211l-.11.52c1.06.096 1.128.212 1.005.807L6.57 11.674c-.123.595-.246.71-1.346.806l-.11.52h3.774l.11-.52c-1.06-.095-1.129-.211-1.006-.806z"/></svg>
|
||||
|
After Width: | Height: | Size: 393 B |
12
images/icons/magic_erase.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g id="XMLID_1_">
|
||||
<path id="XMLID_12_" d="M128.4,96.2L64.2,32H32.6v31.6l64.2,64.2L128.4,96.2z M160,0.4h31.6v64.2H160V0.4z M287.5,160.4h64.2V192
|
||||
h-64.2V160.4z M320,64.6V33h-31.6l-64.2,64.2l31.6,31.6L320,64.6z M0,160.4h64.2V192H0V160.4z M160,287.9h31.6v64.2H160V287.9z
|
||||
M31.6,287.9v31.6h31.6l64.2-64.2l-31.6-31.6L31.6,287.9z M504.2,441.4L187,123.2c-9.3-9.3-24.2-9.3-33.5,0L123.7,153
|
||||
c-9.3,9.3-9.3,24.2,0,33.5l318.2,318.2c9.3,9.3,24.2,9.3,33.5,0l29.8-29.8C514.4,465.5,514.4,450.7,504.2,441.4z M240,272
|
||||
l-95.8-95.8l31.6-31.6l95.8,95.8L240,272z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 913 B |
24
images/icons/media.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="548.176px" height="548.176px" viewBox="0 0 548.176 548.176" style="enable-background:new 0 0 548.176 548.176;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M534.75,68.238c-8.945-8.945-19.694-13.417-32.261-13.417H45.681c-12.562,0-23.313,4.471-32.264,13.417
|
||||
C4.471,77.185,0,87.936,0,100.499v347.173c0,12.566,4.471,23.318,13.417,32.264c8.951,8.946,19.702,13.419,32.264,13.419h456.815
|
||||
c12.56,0,23.312-4.473,32.258-13.419c8.945-8.945,13.422-19.697,13.422-32.264V100.499
|
||||
C548.176,87.936,543.699,77.185,534.75,68.238z M511.623,447.672c0,2.478-0.899,4.613-2.707,6.427
|
||||
c-1.81,1.8-3.952,2.703-6.427,2.703H45.681c-2.473,0-4.615-0.903-6.423-2.703c-1.807-1.813-2.712-3.949-2.712-6.427V100.495
|
||||
c0-2.474,0.902-4.611,2.712-6.423c1.809-1.803,3.951-2.708,6.423-2.708h456.815c2.471,0,4.613,0.905,6.42,2.708
|
||||
c1.801,1.812,2.707,3.949,2.707,6.423V447.672L511.623,447.672z"/>
|
||||
<path d="M127.91,237.541c15.229,0,28.171-5.327,38.831-15.987c10.657-10.66,15.987-23.601,15.987-38.826
|
||||
c0-15.23-5.333-28.171-15.987-38.832c-10.66-10.656-23.603-15.986-38.831-15.986c-15.227,0-28.168,5.33-38.828,15.986
|
||||
c-10.656,10.66-15.986,23.601-15.986,38.832c0,15.225,5.327,28.169,15.986,38.826C99.742,232.211,112.683,237.541,127.91,237.541z
|
||||
"/>
|
||||
<polygon points="210.134,319.765 164.452,274.088 73.092,365.447 73.092,420.267 475.085,420.267 475.085,292.36 356.315,173.587
|
||||
"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
11
images/icons/menu.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="124px" height="124px" viewBox="0 0 124 124" style="enable-background:new 0 0 124 124;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M112,6H12C5.4,6,0,11.4,0,18s5.4,12,12,12h100c6.6,0,12-5.4,12-12S118.6,6,112,6z"/>
|
||||
<path d="M112,50H12C5.4,50,0,55.4,0,62c0,6.6,5.4,12,12,12h100c6.6,0,12-5.4,12-12C124,55.4,118.6,50,112,50z"/>
|
||||
<path d="M112,94H12c-6.6,0-12,5.4-12,12s5.4,12,12,12h100c6.6,0,12-5.4,12-12S118.6,94,112,94z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 797 B |
22
images/icons/pencil.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="51.2,353.28 0,512 158.72,460.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
|
||||
<rect x="89.73" y="169.097" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -95.8575 260.3719)" width="353.277" height="153.599"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M504.32,79.36L432.64,7.68c-10.24-10.24-25.6-10.24-35.84,0l-23.04,23.04l107.52,107.52l23.04-23.04
|
||||
C514.56,104.96,514.56,89.6,504.32,79.36z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 767 B |
19
images/icons/pick_color.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 296.135 296.135" style="enable-background:new 0 0 296.135 296.135;" xml:space="preserve">
|
||||
<path d="M284.5,11.635C276.997,4.132,267.021,0,256.411,0s-20.586,4.132-28.089,11.635l-64.681,64.68l-6.658-6.658
|
||||
c-2.777-2.777-6.2-4.512-9.786-5.206c-0.598-0.116-1.2-0.202-1.804-0.26s-1.211-0.087-1.817-0.087s-1.213,0.029-1.817,0.087
|
||||
s-1.206,0.145-1.804,0.26c-3.585,0.694-7.009,2.43-9.786,5.206v0c-1.388,1.388-2.516,2.938-3.384,4.59
|
||||
c-0.289,0.55-0.55,1.112-0.781,1.683c-0.694,1.712-1.128,3.505-1.302,5.317c-0.058,0.604-0.087,1.211-0.087,1.817
|
||||
c0,1.213,0.116,2.426,0.347,3.621c0.347,1.793,0.954,3.545,1.822,5.196c0.868,1.651,1.996,3.201,3.384,4.59l4.319,4.319
|
||||
L21.468,213.811c-1.434,1.434-2.563,3.143-3.316,5.025l-16.19,40.387c-3.326,8.298-2.338,17.648,2.644,25.013
|
||||
c5.04,7.451,13.356,11.899,22.244,11.899c3.432,0,6.817-0.659,10.063-1.961L77.3,277.984c1.882-0.754,3.592-1.883,5.025-3.316
|
||||
l113.021-113.021l4.318,4.318c0.463,0.463,0.944,0.897,1.44,1.302c0.993,0.81,2.049,1.504,3.15,2.083
|
||||
c2.752,1.446,5.785,2.169,8.818,2.169l0,0c0.029,0,0.058-0.004,0.087-0.004c1.791-0.008,3.58-0.264,5.312-0.777
|
||||
c2.345-0.694,4.583-1.851,6.569-3.471c0.497-0.405,0.977-0.839,1.44-1.302v0c2.314-2.314,3.905-5.077,4.772-8.009
|
||||
c0.694-2.345,0.926-4.798,0.694-7.216c-0.116-1.209-0.347-2.408-0.694-3.581s-0.81-2.318-1.388-3.419
|
||||
c-0.868-1.651-1.996-3.201-3.384-4.59l-6.658-6.658l64.68-64.68C299.988,52.326,299.988,27.124,284.5,11.635z M63.285,251.282
|
||||
l-30.764,12.331l12.332-30.763l110.848-110.848l18.432,18.432L63.285,251.282z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
15
images/icons/refresh.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M403.678,272c0,40.005-15.615,77.651-43.989,106.011C331.33,406.385,293.683,422,253.678,422
|
||||
c-40.005,0-77.651-15.615-106.011-43.989c-28.374-28.359-43.989-66.006-43.989-106.011s15.615-77.651,43.989-106.011
|
||||
C176.027,137.615,213.673,122,253.678,122c25.298,0,49.849,6.343,71.88,18.472L267.023,212h231.299L440.49,0l-57.393,70.13
|
||||
C344.323,45.14,299.865,32,253.678,32c-64.116,0-124.395,24.961-169.702,70.298C38.639,147.605,13.678,207.884,13.678,272
|
||||
s24.961,124.395,70.298,169.702C129.284,487.039,189.562,512,253.678,512s124.395-24.961,169.702-70.298
|
||||
c45.337-45.308,70.298-105.586,70.298-169.702v-15h-90V272z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1008 B |
14
images/icons/select.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 262.474 262.474" style="enable-background:new 0 0 262.474 262.474;" xml:space="preserve">
|
||||
<g id="XMLID_351_">
|
||||
<path id="XMLID_352_" d="M217.327,210.541l-38.815-71.507l31.813-17.271c4.652-2.525,7.628-7.315,7.833-12.604
|
||||
c0.204-5.289-2.395-10.294-6.837-13.17L66.756,2.408c-4.609-2.984-10.481-3.211-15.308-0.591c-4.826,2.62-7.835,7.667-7.844,13.159
|
||||
l-0.277,172.206c-0.008,5.293,2.773,10.198,7.32,12.909c4.545,2.709,10.185,2.824,14.836,0.298l31.811-17.268l38.816,71.506
|
||||
c2.718,5.007,7.873,7.847,13.196,7.847c2.417,0,4.869-0.586,7.143-1.82l54.849-29.774
|
||||
C218.58,226.928,221.279,217.822,217.327,210.541z M155.321,227.132l-38.816-71.507c-1.898-3.496-5.107-6.095-8.922-7.225
|
||||
c-1.395-0.414-2.831-0.618-4.261-0.618c-2.478,0-4.94,0.614-7.157,1.817l-22.797,12.376L73.56,42.55l100.255,64.898l-22.799,12.377
|
||||
c-7.281,3.952-9.979,13.058-6.027,20.338l38.815,71.507L155.321,227.132z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
69
images/icons/selection.svg
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 511.997 511.997" style="enable-background:new 0 0 511.997 511.997;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="137.809" y="471.577" width="89.817" height="39.919"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="283.463" y="471.577" width="89.817" height="39.919"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M60.963,471.581c-11.579,0-21-9.421-21-21.001v-19.959H0.044v19.959c0,33.592,27.327,60.92,60.919,60.92h19.959v-39.919
|
||||
H60.963z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M471.083,430.621v19.959c0,11.58-9.42,21.001-21,21.001h-19.959V511.5h19.959c33.592,0,60.919-27.328,60.919-60.92
|
||||
v-19.959H471.083z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="137.809" y="0.497" width="89.817" height="39.919"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="283.463" y="0.497" width="89.817" height="39.919"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M60.963,0.497c-33.592,0-60.92,27.328-60.92,60.92v19.959h39.919h0.001V61.417c0-11.58,9.42-21.001,21-21.001h19.959
|
||||
V0.497H60.963z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M450.083,0.497h-19.959v39.919h19.959c11.579,0,21,9.421,21,21.001v19.959h39.919V61.417
|
||||
C511.002,27.825,483.675,0.497,450.083,0.497z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect y="288.909" width="39.919" height="89.817"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect y="143.246" width="39.919" height="89.817"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="472.078" y="288.909" width="39.919" height="89.817"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="472.078" y="143.246" width="39.919" height="89.817"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
6
images/icons/shape.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1 2 31 27" x="0px" y="0px">
|
||||
<title>shapes</title>
|
||||
<g>
|
||||
<path d="M30.87,16.33l-7.5-13a1,1,0,0,0-1.73,0l-5,8.69a8.15,8.15,0,0,0-1.61,0V7a1,1,0,0,0-1-1H2A1,1,0,0,0,1,7V19a1,1,0,0,0,1,1H8a8,8,0,1,0,15.69-2.17H30a1,1,0,0,0,.87-1.5ZM3,18V8H13v4.58l0,0A8,8,0,0,0,8.28,18H3Zm13,8a6,6,0,0,1-6-6,4.62,4.62,0,0,1,.07-.86,6,6,0,0,1,4.22-4.89A5.92,5.92,0,0,1,16,14a5.29,5.29,0,0,1,1,.09A6,6,0,0,1,16,26Zm6.83-10.17h0a8,8,0,0,0-4.12-3.34l0,0L22.5,5.84l5.77,10Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 514 B |
13
images/icons/sharpen.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M508.867,190.394l-111-143.568C394.996,43.113,390.52,41,386,41H126c-4.498,0-8.98,2.092-11.867,5.825l-111,143.568
|
||||
c-4.509,5.832-4.112,14.076,0.937,19.447l241,256.432c2.655,2.824,6.568,4.728,10.93,4.728c4.3,0,8.221-1.845,10.93-4.728
|
||||
l241-256.432C512.979,204.469,513.376,196.226,508.867,190.394z M241,418.137L34.694,198.62l93.584-121.043L241,172.957V418.137z
|
||||
M256,146.351L166.949,71h178.102L256,146.351z M271,418.137v-245.18l112.722-95.38l93.585,121.043L271,418.137z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 867 B |
4
images/icons/strikethrough.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.527 13.164c-2.153 0-3.589-1.107-3.705-2.81h1.23c.144 1.06 1.129 1.703 2.544 1.703 1.34 0 2.31-.705 2.31-1.675 0-.827-.547-1.374-1.914-1.675L8.046 8.5h3.45c.468.437.675.994.675 1.697 0 1.826-1.436 2.967-3.644 2.967zM6.602 6.5H5.167a2.776 2.776 0 0 1-.099-.76c0-1.627 1.436-2.768 3.48-2.768 1.969 0 3.39 1.175 3.445 2.85h-1.23c-.11-1.08-.964-1.743-2.25-1.743-1.23 0-2.18.602-2.18 1.607 0 .31.083.581.27.814z"/><path fill-rule="evenodd" d="M15 8.5H1v-1h14v1z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 608 B |
14
images/icons/text.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="977.7px" height="977.7px" viewBox="0 0 977.7 977.7" style="enable-background:new 0 0 977.7 977.7;" xml:space="preserve"
|
||||
>
|
||||
<g>
|
||||
<path d="M770.7,930.6v-35.301c0-23.398-18-42.898-41.3-44.799c-17.9-1.5-35.8-3.1-53.7-5c-34.5-3.6-72.5-7.4-72.5-50.301L603,131.7
|
||||
c136-2,210.5,76.7,250,193.2c6.3,18.7,23.8,31.3,43.5,31.3h36.2c24.9,0,45-20.1,45-45V47.1c0-24.9-20.1-45-45-45H488.9h-0.2H45
|
||||
c-24.9,0-45,20.1-45,45v264.1c0,24.9,20.1,45,45,45h36.2c19.7,0,37.2-12.6,43.5-31.3c39.4-116.5,114-195.2,250-193.2l-0.3,663.5
|
||||
c0,42.9-38,46.701-72.5,50.301c-17.9,1.9-35.8,3.5-53.7,5c-23.3,1.9-41.3,21.4-41.3,44.799V930.6c0,24.9,20.1,45,45,45h236.8h0.3
|
||||
h236.7C750.5,975.6,770.7,955.401,770.7,930.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
2
images/icons/underline.svg
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-type-underline" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M5.313 3.136h-1.23V9.54c0 2.105 1.47 3.623 3.917 3.623s3.917-1.518 3.917-3.623V3.136h-1.23v6.323c0 1.49-.978 2.57-2.687 2.57-1.709 0-2.687-1.08-2.687-2.57V3.136z"/><path fill-rule="evenodd" d="M12.5 15h-9v-1h9v1z"/></svg>
|
||||
|
After Width: | Height: | Size: 408 B |
1
images/icons/undo.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M18.885 3.515c-4.617-4.618-12.056-4.676-16.756-.195l-2.129-2.258v7.938h7.484l-2.066-2.191c2.82-2.706 7.297-2.676 10.073.1 4.341 4.341 1.737 12.291-5.491 12.291v4.8c3.708 0 6.614-1.244 8.885-3.515 4.686-4.686 4.686-12.284 0-16.97z"/></svg>
|
||||
|
After Width: | Height: | Size: 330 B |
20
images/icons/view.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 461.312 461.312" style="enable-background:new 0 0 461.312 461.312;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M230.656,156.416c-40.96,0-74.24,33.28-74.24,74.24s33.28,74.24,74.24,74.24s74.24-33.28,74.24-74.24
|
||||
S271.616,156.416,230.656,156.416z M225.024,208.64c-9.216,0-16.896,7.68-16.896,16.896h-24.576
|
||||
c0.512-23.04,18.944-41.472,41.472-41.472V208.64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M455.936,215.296c-25.088-31.232-114.688-133.12-225.28-133.12S30.464,184.064,5.376,215.296
|
||||
c-7.168,8.704-7.168,21.504,0,30.72c25.088,31.232,114.688,133.12,225.28,133.12s200.192-101.888,225.28-133.12
|
||||
C463.104,237.312,463.104,224.512,455.936,215.296z M230.656,338.176c-59.392,0-107.52-48.128-107.52-107.52
|
||||
s48.128-107.52,107.52-107.52s107.52,48.128,107.52,107.52S290.048,338.176,230.656,338.176z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
images/logo.png
|
Before Width: | Height: | Size: 1.4 KiB |
8
images/logo.svg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
images/manifest/144x144.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
images/manifest/168x168.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
images/manifest/192x192.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
images/manifest/48x48.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
images/manifest/72x72.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
images/manifest/96x96.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 11 KiB |
1809
images/test-collection.json
Normal file
68
index.html
@ -5,24 +5,25 @@
|
||||
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
||||
<title>miniPaint - image editor</title>
|
||||
<meta name="description" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
|
||||
<meta name="keywords" content="photo, image, picture, transparent, layers, free, edit, html5, canvas, javascript, online, photoshop, gimp, effects, sharpen, blur, magic wand tool, clone tool, rotate, resize, photoshop online, online tools, tilt shift, sprites, keypoints" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="shortcut icon" href="images/favicon.png?v2" />
|
||||
<meta name="keywords" content="photo, image, picture, transparent, layers, free, edit, html5, canvas, javascript, online, photoshop, gimp, effects, sharpen, blur, magic eraser tool, clone tool, rotate, resize, photoshop online, online tools, tilt shift, sprites, keypoints" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" />
|
||||
<link rel="icon" sizes="192x192" href="images/favicon.png">
|
||||
<!-- <link rel="manifest" href="dist/manifest.json"> -->
|
||||
<!-- Google -->
|
||||
<meta itemprop="name" content="miniPaint" />
|
||||
<meta itemprop="description" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
|
||||
<meta itemprop="image" content="http://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<meta itemprop="image" content="https://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="miniPaint" />
|
||||
<meta name="twitter:description" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
|
||||
<meta name="twitter:image" content="http://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<meta name="twitter:image" content="https://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<meta name="twitter:image:alt" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
|
||||
<!-- Facebook, Pinterest -->
|
||||
<meta property="og:title" content="miniPaint" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:url" content="http://viliusle.github.io/miniPaint/" />
|
||||
<meta property="og:image" content="http://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<meta property="og:url" content="https://viliusle.github.io/miniPaint/" />
|
||||
<meta property="og:image" content="https://viliusle.github.io/miniPaint/images/preview.jpg" />
|
||||
<meta property="og:description" content="miniPaint is free online image editor using HTML5. Edit, adjust your images, add effects online in your browser, without installing anything..." />
|
||||
<meta property="og:site_name" content="miniPaint" />
|
||||
|
||||
@ -30,24 +31,35 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
<nav aria-label="Main Menu" class="main_menu" id="main_menu"></nav>
|
||||
|
||||
<div class="submenu">
|
||||
<a class="logo" href="">miniPaint</a>
|
||||
<a class="logo" href="#">miniPaint</a>
|
||||
<div class="block attributes" id="action_attributes"></div>
|
||||
<div class="clear"></div>
|
||||
<button class="undo_button" id="undo_button" type="button">
|
||||
<span class="sr_only">Undo</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sidebar_left" id="tools_container"></div>
|
||||
|
||||
<div class="main_wrapper" id="main_wrapper">
|
||||
<div class="canvas_wrapper" id="canvas_wrapper">
|
||||
<div id="mouse"></div>
|
||||
<div class="transparent-grid" id="canvas_minipaint_background"></div>
|
||||
<canvas id="canvas_minipaint">
|
||||
<div class="trn error">
|
||||
Your browser does not support canvas or JavaScript is not enabled.
|
||||
</div>
|
||||
</canvas>
|
||||
|
||||
|
||||
<div class="middle_area" id="middle_area">
|
||||
|
||||
<canvas class="ruler_left" id="ruler_left"></canvas>
|
||||
<canvas class="ruler_top" id="ruler_top"></canvas>
|
||||
|
||||
<div class="main_wrapper" id="main_wrapper">
|
||||
<div class="canvas_wrapper" id="canvas_wrapper">
|
||||
<div id="mouse"></div>
|
||||
<div class="transparent-grid" id="canvas_minipaint_background"></div>
|
||||
<canvas id="canvas_minipaint">
|
||||
<div class="trn error">
|
||||
Your browser does not support canvas or JavaScript is not enabled.
|
||||
</div>
|
||||
</canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -59,12 +71,6 @@
|
||||
|
||||
<div class="colors block">
|
||||
<h2 class="trn toggle" data-target="toggle_colors">Colors</h2>
|
||||
<input
|
||||
title="Click to change color"
|
||||
type="color"
|
||||
class="color_area"
|
||||
id="main_color"
|
||||
value="#0000ff" />
|
||||
<div class="content" id="toggle_colors"></div>
|
||||
</div>
|
||||
|
||||
@ -75,7 +81,7 @@
|
||||
|
||||
<div class="details block" id="details_base">
|
||||
<h2 class="trn toggle toggle-full" data-target="toggle_details">Layer details</h2>
|
||||
<div class="content" id="toggle_details"></div>
|
||||
<div class="content details-content" id="toggle_details"></div>
|
||||
</div>
|
||||
|
||||
<div class="layers block">
|
||||
@ -85,10 +91,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile_menu">
|
||||
<button class="right_mobile_menu" id="mobile_menu_button" type="button"></button>
|
||||
<button class="left_mobile_menu" id="left_mobile_menu_button" type="button">
|
||||
<span class="sr_only">Toggle Menu</span>
|
||||
</button>
|
||||
<button class="right_mobile_menu" id="mobile_menu_button" type="button">
|
||||
<span class="sr_only">Toggle Menu</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ddsmoothmenu" id="main_menu"></div>
|
||||
<div class="hidden" id="tmp"></div>
|
||||
<div id="popup"></div>
|
||||
<div id="popups"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
41
manifest-disabled.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "miniPaint",
|
||||
"short_name": "miniPaint",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "landscape",
|
||||
"background_color": "#666d6f",
|
||||
"description": "miniPaint is free online image editor using HTML5.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "images/manifest/48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/manifest/72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/manifest/96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/manifest/144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/manifest/168x168.png",
|
||||
"sizes": "168x168",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/manifest/192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
15577
package-lock.json
generated
43
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "miniPaint",
|
||||
"version": "4.0.1",
|
||||
"version": "4.14.2",
|
||||
"author": "Vilius L.",
|
||||
"description": "Online graphics editing tool lets create, edit images using HTML5 technologies.",
|
||||
"keywords": [
|
||||
@ -10,31 +10,42 @@
|
||||
"layers",
|
||||
"effects"
|
||||
],
|
||||
"scripts": {
|
||||
"server": "webpack serve --mode development --env development --open",
|
||||
"dev": "webpack --mode development",
|
||||
"build": "webpack --mode production"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/viliusle/miniPaint"
|
||||
},
|
||||
"homepage": "https://github.com/viliusle/miniPaint",
|
||||
"license": "GPL-3.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"amd-optimize": "^0.6.1",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"source-map-loader": "^0.2.3",
|
||||
"style-loader": "^0.19.0",
|
||||
"webpack": "^3.9.1",
|
||||
"webpack-dev-server": "^2.9.5"
|
||||
"@babel/core": "^7.14.5",
|
||||
"@babel/plugin-transform-runtime": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.5",
|
||||
"babel-loader": "^8.2.2",
|
||||
"css-loader": "^5.2.6",
|
||||
"source-map-loader": "^3.0.0",
|
||||
"style-loader": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-dev-server": "^4.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"alertifyjs": "^1.11.0",
|
||||
"blueimp-canvas-to-blob": "^3.14.0",
|
||||
"@babel/runtime": "^7.14.5",
|
||||
"alertifyjs": "^1.13.1",
|
||||
"blueimp-canvas-to-blob": "^3.28.0",
|
||||
"exif-js": "^2.3.0",
|
||||
"file-saver": "^1.3.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"fuzzysort": "^1.1.4",
|
||||
"gif.js.optimized": "^1.0.1",
|
||||
"hermite-resize": "git+https://github.com/viliusle/Hermite-resize.git",
|
||||
"jquery": "^3.2.1"
|
||||
"jquery": "^3.5.1",
|
||||
"pica": "^7.0.0",
|
||||
"semver-compare": "^1.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"webfontloader": "^1.6.28"
|
||||
}
|
||||
}
|
||||
|
||||
68
service-worker.js
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
//IMPORTANT - this file is not used !!!
|
||||
|
||||
|
||||
// use a cacheName for cache versioning
|
||||
var cacheName = 'v1:static';
|
||||
|
||||
// during the install phase you usually want to cache static assets
|
||||
self.addEventListener('install', function(e) {
|
||||
// once the SW is installed, go ahead and fetch the resources to make this work offline
|
||||
e.waitUntil(
|
||||
caches.open(cacheName).then(function(cache) {
|
||||
return cache.addAll([
|
||||
'./',
|
||||
'./dist/bundle.js',
|
||||
'./images/favicon.png',
|
||||
'./images/logo.svg',
|
||||
'./images/logo-colors.png',
|
||||
'./images/icons/animation.svg',
|
||||
'./images/icons/blur.svg',
|
||||
'./images/icons/bold.svg',
|
||||
'./images/icons/brush.svg',
|
||||
'./images/icons/bulge_pinch.svg',
|
||||
'./images/icons/clone.svg',
|
||||
'./images/icons/crop.svg',
|
||||
'./images/icons/delete.svg',
|
||||
'./images/icons/desaturate.svg',
|
||||
'./images/icons/erase.svg',
|
||||
'./images/icons/external.png',
|
||||
'./images/icons/fill.svg',
|
||||
'./images/icons/gradient.png',
|
||||
'./images/icons/grid.png',
|
||||
'./images/icons/italic.svg',
|
||||
'./images/icons/magic_erase.svg',
|
||||
'./images/icons/media.svg',
|
||||
'./images/icons/menu.svg',
|
||||
'./images/icons/pencil.svg',
|
||||
'./images/icons/pick_color.svg',
|
||||
'./images/icons/refresh.svg',
|
||||
'./images/icons/select.svg',
|
||||
'./images/icons/selection.svg',
|
||||
'./images/icons/shape.svg',
|
||||
'./images/icons/sharpen.svg',
|
||||
'./images/icons/strikethrough.svg',
|
||||
'./images/icons/text.svg',
|
||||
'./images/icons/underline.svg',
|
||||
'./images/icons/view.svg'
|
||||
]).then(function() {
|
||||
self.skipWaiting();
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// when the browser fetches a url
|
||||
self.addEventListener('fetch', function(event) {
|
||||
// either respond with the cached object or go ahead and fetch the actual url
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(function(response) {
|
||||
if (response) {
|
||||
// retrieve from cache
|
||||
return response;
|
||||
}
|
||||
// fetch as normal
|
||||
return fetch(event.request);
|
||||
})
|
||||
);
|
||||
});
|
||||
732
src/css/component.css
Normal file
@ -0,0 +1,732 @@
|
||||
/*****************\
|
||||
| UI Button Group |
|
||||
\*****************/
|
||||
|
||||
.ui_button_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.ui_button_group.no_wrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.ui_button_group.stacked {
|
||||
margin: .75rem 0;
|
||||
}
|
||||
.ui_button_group.stacked:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui_button_group.stacked:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui_button_group > button,
|
||||
.ui_button_group > input[type="button"] {
|
||||
border-radius: 0;
|
||||
}
|
||||
.ui_button_group > button:focus,
|
||||
.ui_button_group > input[type="button"]:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
.ui_button_group > button + button,
|
||||
.ui_button_group > button + input[type="button"],
|
||||
.ui_button_group > input[type="button"] + button,
|
||||
.ui_button_group > input[type="button"] + input[type="button"] {
|
||||
margin-left: -1px;
|
||||
}
|
||||
.ui_button_group > button:first-child,
|
||||
.ui_button_group > input[type="button"]:first-child {
|
||||
border-radius: var(--button-border-radius) 0 0 var(--button-border-radius);
|
||||
}
|
||||
.ui_button_group > button:last-child,
|
||||
.ui_button_group > input[type="button"]:last-child {
|
||||
border-radius: 0 var(--button-border-radius) var(--button-border-radius) 0;
|
||||
}
|
||||
|
||||
/****************\
|
||||
| UI Color Input |
|
||||
\****************/
|
||||
|
||||
.ui_color_input {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ui_color_input input[type="color"] {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
border: .2rem solid var(--input-background-color);
|
||||
width: 3rem;
|
||||
}
|
||||
|
||||
.ui_color_input .alpha_overlay {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw1AUhU9bRdGKiBlERDJUJwuiIo5ahSJUCLVCqw4mL/2DJg1Jiouj4Fpw8Gex6uDirKuDqyAI/oA4OTopukiJ9yWFFjFeeLyP8+45vHcfEKyVmGa1jQOabpvJeExMZ1bFjld0YxgBCOiTmWXMSVICvvV1T51Ud1Ge5d/3Z/WoWYsBAZF4lhmmTbxBPL1pG5z3iQVWkFXic+Ixky5I/Mh1xeM3znmXgzxTMFPJeWKBWMy3sNLCrGBqxFPEEVXTKT+Y9ljlvMVZK1VY4578heGsvrLMdVpDiGMRS5AgQkEFRZRgI0q7ToqFJJ3HfPyDrl8il0KuIhg5FlCGBtn1g//B79lauckJLykcA9pfHOdjBOjYBepVx/k+dpz6CRB6Bq70pr9cA2Y+Sa82tcgR0LsNXFw3NWUPuNwBBp4M2ZRdKUQrmMsB72f0TRmg/xboWvPm1jjH6QOQolklboCDQ2A0T9nrPu/ubJ3bvz2N+f0AL+pyjMZuudYAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfkCx4BHwaj7CMVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAC5JREFUOMtjfPfuHQNuICgoiEeWiYECMKp5ZGhm/P//Px7p9+/fjwbYqGZKNAMAANAI7r7rfkQAAAAASUVORK5CYII=');
|
||||
background-size: 100% 100%;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
right: 3px;
|
||||
bottom: 3px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/**************************\
|
||||
| UI Color Picker Gradient |
|
||||
\**************************/
|
||||
|
||||
.ui_color_picker_gradient {
|
||||
padding: 0 0 80% 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .primary_pick {
|
||||
position: absolute;
|
||||
left: 86%;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 17%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
border: 1px solid var(--border-color);
|
||||
background: green;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick:focus {
|
||||
outline: 0;
|
||||
border: 1px solid var(--input-border-color-active);
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick .saturation_gradient {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick .value_gradient {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick .handle {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: auto;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick .handle:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -.6rem;
|
||||
top: -.6rem;
|
||||
height: .3rem;
|
||||
width: .3rem;
|
||||
border: .4rem solid #999;
|
||||
border-radius: 1000px;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .secondary_pick .handle:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -.5rem;
|
||||
top: -.5rem;
|
||||
height: .5rem;
|
||||
width: .5rem;
|
||||
border: .2rem solid white;
|
||||
border-radius: 1000px;
|
||||
}
|
||||
|
||||
.ui_color_picker_gradient .primary_pick .ui_range {
|
||||
border-color: rgba(1, 1, 1, 0.1);
|
||||
}
|
||||
.ui_color_picker_gradient .primary_pick .ui_range:focus {
|
||||
border-color: var(--input-border-color-active);
|
||||
}
|
||||
|
||||
/*****************\
|
||||
| UI Color Sample |
|
||||
\*****************/
|
||||
|
||||
.ui_color_sample {
|
||||
border: 1px solid #999;
|
||||
box-shadow: 0 0 0 1px #555 inset;
|
||||
display: block;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
/***************\
|
||||
| UI Flex Group |
|
||||
\***************/
|
||||
|
||||
.ui_flex_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.ui_flex_group.stacked {
|
||||
margin: .75rem 0;
|
||||
}
|
||||
.ui_flex_group.stacked:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui_flex_group.stacked:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui_flex_group.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
.ui_flex_group.justify_content_center {
|
||||
justify-content: center;
|
||||
}
|
||||
.ui_flex_group.justify_content_start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.ui_flex_group.justify_content_end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.ui_flex_group.justify_content_space_around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
.ui_flex_group.justify_content_space_between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.ui_flex_group.align_items_baseline {
|
||||
align-items: baseline;
|
||||
}
|
||||
.ui_flex_group.align_items_center {
|
||||
align-items: center;
|
||||
}
|
||||
.ui_flex_group.align_items_start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
.ui_flex_group.align_items_end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
.ui_flex_group.align_items_stretch {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/****************\
|
||||
| UI Icon Button |
|
||||
\****************/
|
||||
|
||||
.ui_icon_button {
|
||||
height: 2.8rem;
|
||||
line-height: 2.8rem;
|
||||
}
|
||||
|
||||
.ui_icon_button.input_height {
|
||||
height: 2.4rem;
|
||||
line-height: 2.4rem;
|
||||
}
|
||||
|
||||
.ui_icon_button > svg {
|
||||
display: block;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.ui_icon_button > img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
button img{
|
||||
filter: var(--menu-icons-filter);
|
||||
}
|
||||
|
||||
/****************\
|
||||
| UI Input Group |
|
||||
\****************/
|
||||
|
||||
.ui_input_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-height: 2.4rem;
|
||||
width: 100%;
|
||||
}
|
||||
.ui_input_group.stacked {
|
||||
margin: .75rem 0;
|
||||
}
|
||||
.ui_input_group.stacked:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui_input_group.stacked:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui_input_group > input,
|
||||
.ui_input_group > .ui_number_input,
|
||||
.ui_input_group > .ui_range,
|
||||
.ui_input_group > .ui_color_sample {
|
||||
border-radius: 0;
|
||||
height: auto;
|
||||
min-width: 0;
|
||||
}
|
||||
.ui_input_group > .ui_color_sample {
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
.ui_input_group > :first-child {
|
||||
border-radius: var(--input-border-radius) 0 0 var(--input-border-radius);
|
||||
}
|
||||
.ui_input_group > :last-child {
|
||||
border-radius: 0 var(--input-border-radius) var(--input-border-radius) 0;
|
||||
}
|
||||
.ui_input_group > label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid var(--input-group-border-color);
|
||||
border-right: 0;
|
||||
margin: 0;
|
||||
padding: 0 .75rem;
|
||||
}
|
||||
.ui_input_group > .ui_range + input,
|
||||
.ui_input_group > .ui_range + .ui_number_input {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.ui_input_grid {
|
||||
border-radius: var(--input-border-radius);
|
||||
box-shadow: 0 1px 0 0 rgba(1, 1, 1, 0.1);
|
||||
}
|
||||
.ui_input_grid.stacked {
|
||||
margin: .75rem 0;
|
||||
}
|
||||
.ui_input_grid.stacked:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui_input_grid.stacked:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
:not(.ui_input_grid) > .ui_input_group {
|
||||
border-radius: var(--input-border-radius);
|
||||
box-shadow: 0 1px 0 0 rgba(1, 1, 1, 0.1);
|
||||
}
|
||||
.ui_input_grid > .ui_input_group {
|
||||
margin: -1px 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group > :first-child,
|
||||
.ui_input_grid > .ui_input_group > :last-child {
|
||||
border-radius: 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:first-child > :first-child {
|
||||
border-radius: var(--input-border-radius) 0 0 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:first-child > :last-child {
|
||||
border-radius: 0 var(--input-border-radius) 0 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:last-child > :first-child {
|
||||
border-radius: 0 0 0 var(--input-border-radius);
|
||||
}
|
||||
.ui_input_grid > .ui_input_group:last-child > :last-child {
|
||||
border-radius: 0 0 var(--input-border-radius) 0;
|
||||
}
|
||||
|
||||
/*****************\
|
||||
| UI Number Input |
|
||||
\*****************/
|
||||
|
||||
.ui_number_input {
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-radius: var(--input-border-radius);
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ui_number_input > input[type="number"]::-webkit-outer-spin-button,
|
||||
.ui_number_input > input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ui_number_input > input[type="number"] {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
padding-right: 2.5rem;
|
||||
padding-right: calc(var(--number-input-arrow-width) + .5rem);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui_number_input > .increase_number,
|
||||
.ui_number_input > .decrease_number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
width: 2rem;
|
||||
width: var(--number-input-arrow-width);
|
||||
border-radius: 0;
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-right: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.ui_number_input > ::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
.ui_number_input > .increase_number:focus,
|
||||
.ui_number_input > .decrease_number:focus {
|
||||
outline: 0;
|
||||
}
|
||||
.ui_number_input > .increase_number {
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 50%;
|
||||
border-top: none;
|
||||
}
|
||||
.ui_number_input > .increase_number::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
border-bottom: 3px solid var(--input-text-color);
|
||||
}
|
||||
.ui_number_input > .decrease_number {
|
||||
right: 0;
|
||||
top: calc(50% - 1px);
|
||||
bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
.ui_number_input > .decrease_number::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
border-top: 3px solid var(--input-text-color);
|
||||
}
|
||||
|
||||
/**********\
|
||||
| UI Range |
|
||||
\**********/
|
||||
|
||||
:root {
|
||||
--range-handle-width: 18px;
|
||||
}
|
||||
|
||||
.ui_range {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: var(--input-background-color);
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-radius: 1000px;
|
||||
height: 1.8rem;
|
||||
overflow: visible;
|
||||
outline: 0;
|
||||
padding: 0 calc(var(--range-handle-width) / 2);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.ui_range:focus {
|
||||
border-color: var(--input-border-color-active);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ui_range.active {
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.ui_range .padded_track {
|
||||
position: absolute;
|
||||
left: calc(var(--range-handle-width) / 2);
|
||||
right: calc(var(--range-handle-width) / 2);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ui_range .bar {
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
.ui_range .handle {
|
||||
background: var(--input-text-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 1000px;
|
||||
box-sizing: border-box;
|
||||
cursor: col-resize;
|
||||
display: block;
|
||||
height: 1.8rem;
|
||||
width: var(--range-handle-width);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
|
||||
.ui_range.color_picker .handle {
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transform: translateX(50%);
|
||||
}
|
||||
|
||||
.ui_range.color_picker .handle::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: .5rem solid transparent;
|
||||
border-right: .5rem solid transparent;
|
||||
border-top: .7rem solid white;
|
||||
}
|
||||
.ui_range.color_picker .handle::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: .5rem solid transparent;
|
||||
border-right: .5rem solid transparent;
|
||||
border-bottom: .7rem solid black;
|
||||
}
|
||||
.ui_range.color_picker .handle:hover::before {
|
||||
border-top-color: #eaeaea;
|
||||
}
|
||||
.ui_range.color_picker .handle:hover::after {
|
||||
border-bottom-color: #222;
|
||||
}
|
||||
|
||||
.ui_range.vertical {
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
height: 100%;
|
||||
width: 1.8rem;
|
||||
padding: calc(var(--range-handle-width) / 2) 0;
|
||||
}
|
||||
|
||||
.ui_range.vertical.active {
|
||||
cursor: row-resize;
|
||||
}
|
||||
|
||||
.ui_range.vertical .padded_track {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: calc(var(--range-handle-width) / 2);
|
||||
bottom: calc(var(--range-handle-width) / 2);
|
||||
}
|
||||
|
||||
.ui_range.vertical .bar {
|
||||
width: 100%;
|
||||
height: 0%;
|
||||
}
|
||||
|
||||
.ui_range.vertical .handle {
|
||||
transform: translate(50%, -50%);
|
||||
top: 0;
|
||||
right: 50%;
|
||||
cursor: row-resize;
|
||||
}
|
||||
|
||||
.ui_range.vertical.color_picker_thin {
|
||||
padding: 1px 0;
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui_range.vertical.color_picker_thin .padded_track {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ui_range.vertical.color_picker_thin .handle {
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
height: .5rem;
|
||||
}
|
||||
|
||||
/*************\
|
||||
| UI Swatches |
|
||||
\*************/
|
||||
|
||||
.ui_swatches {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui_swatches .swatch_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: auto;
|
||||
border-radius: var(--input-border-radius);
|
||||
border: 1px solid var(--border-color);
|
||||
border-right: transparent;
|
||||
box-shadow: 0 1px 0 0 rgba(1, 1, 1, 0.1);
|
||||
overflow: hidden;
|
||||
max-height: calc(2.3rem);
|
||||
}
|
||||
.ui_swatches .swatch_group:focus {
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 1px var(--input-border-color-active);
|
||||
}
|
||||
|
||||
.ui_swatches .swatch_group.rows_2 {
|
||||
max-height: calc(4.6rem - 1px);
|
||||
}
|
||||
.ui_swatches .swatch_group.rows_3 {
|
||||
max-height: calc(6.9rem - 2px);
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_1 .swatch {
|
||||
width: 100%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_2 .swatch {
|
||||
width: 50%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_3 .swatch {
|
||||
width: 33.33%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_4 .swatch {
|
||||
width: 25%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_5 .swatch {
|
||||
width: 20%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_6 .swatch {
|
||||
width: 16.66%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_7 .swatch {
|
||||
width: 14.29%;
|
||||
}
|
||||
.ui_swatches .swatch_group.cols_8 .swatch {
|
||||
width: 12.5%;
|
||||
}
|
||||
|
||||
.ui_swatches .swatch {
|
||||
background: white;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0 1px white inset;
|
||||
margin: -1px 0 0 -1px;
|
||||
padding: 0;
|
||||
height: 2.3rem;
|
||||
min-width: 2.3rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.ui_swatches .swatch:hover,
|
||||
.ui_swatches .swatch:focus {
|
||||
background: white;
|
||||
box-shadow: 0 0 0 2px white inset, 0 0 0 3px var(--border-color) inset;
|
||||
}
|
||||
.ui_swatches .swatch:hover:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(to bottom right, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 50%, rgba(0, 0, 0, 0.1) 51%, rgba(0, 0, 0, 0.1) 100%);
|
||||
}
|
||||
|
||||
.ui_swatches .swatch.active {
|
||||
box-shadow: 0 0 0 3px var(--button-text-color-active) inset, 0 0 0 4px var(--border-color) inset;
|
||||
}
|
||||
|
||||
|
||||
/******************\
|
||||
| UI Toggle Button |
|
||||
\******************/
|
||||
|
||||
.ui_toggle_button {
|
||||
padding-left: 2.6rem !important;
|
||||
position: relative;
|
||||
}
|
||||
.ui_toggle_button:before {
|
||||
background-color: var(--button-toggle-background-color);
|
||||
background-image: url('data:image/svg+xml;utf8,<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-x" fill="white" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/></svg>');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: var(--button-border-radius) 0 0 var(--button-border-radius);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 1.8rem;
|
||||
content: '';
|
||||
}
|
||||
.ui_toggle_button[aria-pressed="true"]:before {
|
||||
background-color: var(--button-text-color-active);
|
||||
background-image: url('data:image/svg+xml;utf8,<svg width="0.7em" height="1em" viewBox="0 0 16 16" class="bi bi-check2" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg>');
|
||||
}
|
||||
|
||||
/* media */
|
||||
|
||||
.media-paging{
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.media-paging button{
|
||||
background-color: var(--button-background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.media-paging button.selected{
|
||||
background-color: var(--background-color-active);
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
|
||||
/* global search */
|
||||
#global_search_results{
|
||||
padding-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
#global_search_results .search-result {
|
||||
padding: 3px 5px;
|
||||
}
|
||||
#global_search_results .search-result.active{
|
||||
background-color: var(--background-color-active);
|
||||
color: var(--text-color-active);
|
||||
border-radius: 2px;
|
||||
}
|
||||
#global_search_results b{
|
||||
color: var(--text-color-red);
|
||||
}
|
||||
|
||||
.popup.shortcuts table{
|
||||
line-height: 1;
|
||||
}
|
||||
@ -1,8 +1,23 @@
|
||||
.wrapper{
|
||||
height: calc(100vh - 30px);
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
margin: 0;
|
||||
position:relative;
|
||||
position: fixed; /* dont change it, vh does not work on mobiles with bottom footer */
|
||||
top: 30px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 5px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
|
||||
-ms-grid-rows: auto 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
-ms-grid-columns: auto 1fr auto;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
|
||||
grid-template-areas:
|
||||
"submenu submenu submenu"
|
||||
"sidebar_left main sidebar_right";
|
||||
}
|
||||
.trn{}
|
||||
.toggle{
|
||||
@ -11,6 +26,9 @@
|
||||
.hidden{
|
||||
display:none;
|
||||
}
|
||||
.center{
|
||||
text-align: center;
|
||||
}
|
||||
.pointer{
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -32,18 +50,6 @@
|
||||
.grey{
|
||||
color:grey;
|
||||
}
|
||||
.external{
|
||||
padding-right: 15px;
|
||||
}
|
||||
.external:after{
|
||||
position:absolute;
|
||||
content: "";
|
||||
width:10px;
|
||||
height:10px;
|
||||
margin-left: 5px;
|
||||
background: url(images/sprites.png) no-repeat -700px 0;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.noselect {
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
@ -53,36 +59,39 @@
|
||||
user-select: none; /* Non-prefixed version */
|
||||
}
|
||||
.block{
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
background-color: var(--background-color-medium);
|
||||
background-color: var(--block-background-color);
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid var(--background-color-border);
|
||||
padding:5px;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 10px;
|
||||
user-select: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.sidebar_right .block{
|
||||
background-color: #68727b;
|
||||
background-color: var(--block-background-color);
|
||||
border-bottom: none;
|
||||
box-shadow: 0 -2px 0 0 var(--header-background-color) inset;
|
||||
}
|
||||
.block:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.block h2{
|
||||
position: relative;
|
||||
margin: -5px -5px 10px -5px;
|
||||
padding: 2px 5px;
|
||||
padding: 2px 5px 2px 6px;
|
||||
margin: 0;
|
||||
font-size: 110%;
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
background-color: var(--background-color-light);
|
||||
background-color: var(--header-background-color);
|
||||
border-bottom: #555;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
.block h2:after{
|
||||
position:absolute;
|
||||
content:'';
|
||||
height:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom: -2px;
|
||||
border-top: 1px solid #aaa;
|
||||
.block.toggled h2, .block h2.toggled:after{
|
||||
border: none;
|
||||
}
|
||||
.block h2.toggle:before{
|
||||
/* icon */
|
||||
position:absolute;
|
||||
content:'';
|
||||
width: 0;
|
||||
@ -90,12 +99,25 @@
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
border-style: solid;
|
||||
border-width: 0 5px 6px 5px;
|
||||
border-color: transparent transparent #333333 transparent;
|
||||
border-width: 0 4px 5px 4px;
|
||||
border-color: transparent transparent var(--text-color-muted) transparent;
|
||||
}
|
||||
.block h2.toggled:before{
|
||||
border-width: 6px 5px 0 5px;
|
||||
border-color: #333333 transparent transparent transparent;
|
||||
/* icon */
|
||||
border-width: 5px 4px 0 4px;
|
||||
border-color: var(--text-color-muted) transparent transparent transparent;
|
||||
}
|
||||
.block .content{
|
||||
padding: 7.5px 5px;
|
||||
}
|
||||
.block_section {
|
||||
margin: .75rem 0;
|
||||
}
|
||||
.block_section:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.block_section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.error{
|
||||
padding:20px;
|
||||
@ -106,18 +128,30 @@
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
/* color chooser */
|
||||
body .sp-replacer{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
}
|
||||
body .sp-preview{
|
||||
width: calc(100% - 20px);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* ========== header ======================================================== */
|
||||
|
||||
.logo{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
height: 30px;
|
||||
width: 110px;
|
||||
padding: 5px 5px 5px 36px;
|
||||
margin: 5px;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
color: var(--text-color);
|
||||
}
|
||||
.logo:after{
|
||||
position:absolute;
|
||||
@ -126,126 +160,167 @@
|
||||
top: 0;
|
||||
width: 31px;
|
||||
height: 30px;
|
||||
background: url(images/sprites.png) -50px -100px no-repeat;
|
||||
background: url('images/logo.svg') no-repeat center center;
|
||||
background-size: auto 28px;
|
||||
filter: var(--mobile-menu-toggle-filter);
|
||||
}
|
||||
.logo:hover:after{
|
||||
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97);
|
||||
left: 2px;
|
||||
}
|
||||
.about-logo{
|
||||
margin-left:22%;
|
||||
animation:shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97);;
|
||||
}
|
||||
.about-name{
|
||||
font-size:15px;
|
||||
color:#006900;
|
||||
font-weight:bold;
|
||||
}
|
||||
@keyframes shake{
|
||||
10%, 90%{
|
||||
transform: translate(2px, 0px);
|
||||
}
|
||||
20%, 80%{
|
||||
transform: translate(5px 0px);
|
||||
}
|
||||
30%, 50%, 70%{
|
||||
transform: translate(0px 0px;);
|
||||
}
|
||||
40%, 60%{
|
||||
transform: translate(6px 0px);
|
||||
.undo_button {
|
||||
display: none;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
top: 0;
|
||||
border: 0;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
filter: var(--mobile-menu-toggle-filter);
|
||||
background: url(images/icons/undo.svg) no-repeat center center;
|
||||
background-size: auto 25px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.undo_button:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
@media screen and (max-width: 700px){
|
||||
.undo_button {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== sub-header ==================================================== */
|
||||
|
||||
.submenu{
|
||||
height:40px;
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 1;
|
||||
-ms-grid-column-span: 3;
|
||||
grid-area: submenu;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
background-color: var(--background-color-medium);
|
||||
background-color: var(--section-background-color);
|
||||
overflow: hidden;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.attributes{
|
||||
float: left;
|
||||
width: calc(100% - 115px);
|
||||
height: 30px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
background-color: var(--area-background-color);
|
||||
width: calc(100% - 125px);
|
||||
margin-top: 5px;
|
||||
padding: 3px 10px 0 10px;
|
||||
margin-bottom: 5px !important;
|
||||
padding: 3px 10px 3px 10px;
|
||||
border: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
min-height: 30px;
|
||||
}
|
||||
.attributes .item{
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.attributes .item > label {
|
||||
margin: 0 .5rem 0 0;
|
||||
}
|
||||
.attributes input[type="number"]{
|
||||
width: 60px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.attributes button{
|
||||
.attributes input[type="color"] {
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
border: .2rem solid var(--input-background-color);
|
||||
width: 3rem;
|
||||
}
|
||||
.attributes .item > button:not(.ui_icon_button){
|
||||
display: inline-block;
|
||||
padding: 3px 10px;
|
||||
border: 1px solid #444;
|
||||
background-color: transparent;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.attributes button:hover{
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
background-color: var(--background-color-light);
|
||||
}
|
||||
.attributes button.active{
|
||||
background-color: #419147;
|
||||
background-color: var(--background-color-active);
|
||||
}
|
||||
|
||||
/* ========== left sidebar ================================================== */
|
||||
|
||||
.sidebar_left{
|
||||
position: absolute;
|
||||
left:0px;
|
||||
top: 45px;
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 1;
|
||||
grid-area: sidebar_left;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
background-color: var(--section-background-color);
|
||||
padding: 0 5px 5px 0;
|
||||
margin-right: 5px;
|
||||
overflow: hidden;
|
||||
align-self: start;
|
||||
width: 40px;
|
||||
padding: 0 5px;
|
||||
background-color: var(--background-color-medium);
|
||||
overflow-y: auto;
|
||||
max-height: 100%;
|
||||
}
|
||||
.sidebar_left .item{
|
||||
position: relative;
|
||||
display:block;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
background-color: var(--background-color-medium);
|
||||
background-image: url(images/sprites.png);
|
||||
background-repeat: no-repeat;
|
||||
background-color: var(--area-background-color);
|
||||
height: 25px;
|
||||
margin: 5px 0 5px 0;
|
||||
width: 30px;
|
||||
margin: 5px 0 0 5px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
/*filter: grayscale(1);*/
|
||||
}
|
||||
.sidebar_left .item:after{
|
||||
position: absolute;
|
||||
content: '';
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
filter: var(--menu-icons-filter);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
.sidebar_left .item:hover{
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
background-color: var(--background-color-lightest);
|
||||
background-color: var(--background-color-hover);
|
||||
}
|
||||
.sidebar_left .item.active{
|
||||
background-color: #419147;
|
||||
background-color: var(--background-color-active);
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
.sidebar_left .item.active:after{
|
||||
filter: var(--menu-icons-filter-active);
|
||||
}
|
||||
|
||||
.sidebar_left .select{ background-position: -342px 2px; }
|
||||
.sidebar_left .selection{ background-position: -43px -47px; }
|
||||
.sidebar_left .magic_wand{ background-position: -294px -48px; }
|
||||
.sidebar_left .brush{ background-position: 5px 3px; }
|
||||
.sidebar_left .erase{ background-position: -444px 3px; }
|
||||
.sidebar_left .fill{ background-position: -145px 2px; }
|
||||
.sidebar_left .pick_color{ background-position: -644px 3px; }
|
||||
.sidebar_left .pencil{ background-position: -594px 3px; }
|
||||
.sidebar_left .line{ background-position: -193px -46px; }
|
||||
.sidebar_left .text{ background-position: -394px 4px; }
|
||||
.sidebar_left .rectangle{ background-position: -94px -45px; }
|
||||
.sidebar_left .circle{ background-position: -547px 2px; }
|
||||
.sidebar_left .blur{ background-position: -41px 2px; }
|
||||
.sidebar_left .sharpen{ background-position: 6px -47px; }
|
||||
.sidebar_left .desaturate{ background-position: -195px 3px; }
|
||||
.sidebar_left .bulge_pinch{ background-position: -93px 5px; }
|
||||
.sidebar_left .clone{ background-position: -493px 2px; }
|
||||
.sidebar_left .gradient{ background-position: -243px 5px; }
|
||||
.sidebar_left .crop{ background-position: -294px 3px; }
|
||||
.sidebar_left .animation{ background-position: -244px -47px; }
|
||||
.sidebar_left .media{ background-position: -145px -47px; }
|
||||
/*
|
||||
IMPORTANT: any new icon should also must be added on /service-worker.js + its version should be updated - FEATURE DISABLED
|
||||
*/
|
||||
.sidebar_left .select:after{ background-image: url('images/icons/select.svg'); }
|
||||
.sidebar_left .selection:after{ background-image: url('images/icons/selection.svg'); }
|
||||
.sidebar_left .brush:after{ background-image: url('images/icons/brush.svg'); }
|
||||
.sidebar_left .pencil:after{ background-image: url('images/icons/pencil.svg'); }
|
||||
.sidebar_left .pick_color:after{ background-image: url('images/icons/pick_color.svg'); }
|
||||
.sidebar_left .erase:after{ background-image: url('images/icons/erase.svg'); }
|
||||
.sidebar_left .magic_erase:after{ background-image: url('images/icons/magic_erase.svg'); }
|
||||
.sidebar_left .fill:after{ background-image: url('images/icons/fill.svg'); }
|
||||
.sidebar_left .media:after{ background-image: url('images/icons/media.svg'); }
|
||||
.sidebar_left .shape:after{ background-image: url('images/icons/shape.svg'); }
|
||||
.sidebar_left .text:after{ background-image: url('images/icons/text.svg'); background-size: 16px auto; }
|
||||
.sidebar_left .gradient:after{ background-image: url('images/icons/gradient.png'); background-size: 18px 12px; filter: none; }
|
||||
.sidebar_left .clone:after{ background-image: url('images/icons/clone.svg'); }
|
||||
.sidebar_left .crop:after{ background-image: url('images/icons/crop.svg'); }
|
||||
.sidebar_left .blur:after{ background-image: url('images/icons/blur.svg'); }
|
||||
.sidebar_left .sharpen:after{ background-image: url('images/icons/sharpen.svg'); }
|
||||
.sidebar_left .desaturate:after{ background-image: url('images/icons/desaturate.svg'); }
|
||||
.sidebar_left .bulge_pinch:after{ background-image: url('images/icons/bulge_pinch.svg'); }
|
||||
.sidebar_left .animation:after{ background-image: url('images/icons/animation.svg'); }
|
||||
|
||||
@media screen and (max-width:550px){
|
||||
#sidebar_left{
|
||||
@ -256,31 +331,39 @@
|
||||
/* ========== right sidebar ================================================= */
|
||||
|
||||
.sidebar_right{
|
||||
position: absolute;
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 3;
|
||||
grid-area: sidebar_right;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
right: 5px;
|
||||
top: 45px;
|
||||
width: 200px;
|
||||
height: calc(100vh - 80px);
|
||||
background-color: #424F5A;
|
||||
background-color: var(--background-color);
|
||||
transition: 0.2s;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
margin: 0 5px;
|
||||
width: 200px;
|
||||
}
|
||||
.sidebar_right.active{
|
||||
right:0 !important;
|
||||
right: 0 !important;
|
||||
}
|
||||
.sidebar_right .block.layers{
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.sidebar_right .block.layers .content{
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
|
||||
/* preview */
|
||||
.canvas_preview_wrapper{
|
||||
position:relative;
|
||||
height:100px;
|
||||
margin-bottom:10px;
|
||||
margin: 5px 5px 10px 5px;
|
||||
}
|
||||
.canvas_preview_details{
|
||||
padding: 0 5px;
|
||||
}
|
||||
.canvas_preview_details button{
|
||||
margin: 0;
|
||||
}
|
||||
.preview canvas{
|
||||
cursor: pointer;
|
||||
@ -292,46 +375,10 @@
|
||||
/* color */
|
||||
.color_area{
|
||||
border: 1px solid #444;
|
||||
width: 100%;
|
||||
width: calc(100% - 10px);
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.colors .content{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.main_color_alt{
|
||||
border:1px solid #393939;
|
||||
margin-top:10px;
|
||||
width:100%;
|
||||
height:40px;
|
||||
}
|
||||
.main_color_rgb{
|
||||
margin-top:10px;
|
||||
}
|
||||
.main_color_rgb div{
|
||||
display: inline-block;
|
||||
width: calc(50% - 3px);
|
||||
vertical-align: top;
|
||||
}
|
||||
.main_color_rgb span, .hex{
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
width: 35px;
|
||||
}
|
||||
.main_color_rgb input{
|
||||
width:50px;
|
||||
}
|
||||
.main_color_rgb .red{ color:#aa0000; }
|
||||
.main_color_rgb .green{ color:#00aa00; }
|
||||
.main_color_rgb .blue{ color:#0000aa; }
|
||||
.main_color_rgb .alpha{ color: #333333; }
|
||||
|
||||
.color_hex{
|
||||
width: calc(100% - 41px);
|
||||
}
|
||||
#all_colors{
|
||||
margin-top:10px;
|
||||
padding:3px 0px 3px 3px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* layers */
|
||||
@ -343,19 +390,21 @@
|
||||
float:right;
|
||||
margin-left:5px;
|
||||
padding:1px 8px;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
background-color: var(--background-color-medium);
|
||||
border:1px solid #444;
|
||||
border-color: var(--border-color);
|
||||
text-decoration:none;
|
||||
color:#000000;
|
||||
color:var(--text-color);
|
||||
font-size:12px;
|
||||
}
|
||||
.layer_add{
|
||||
display:inline-block;
|
||||
padding:1px 8px;
|
||||
margin-right: 10px;
|
||||
background-color: #419147;
|
||||
background-color: var(--background-color-active);
|
||||
border:1px solid #444;
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-color-active);
|
||||
cursor:pointer;
|
||||
text-decoration:none;
|
||||
}
|
||||
@ -366,29 +415,69 @@
|
||||
display:block;
|
||||
padding:1px 5px 3px 5px;
|
||||
height:19px;
|
||||
width: calc(100% - 44px);
|
||||
text-align: left;
|
||||
overflow:hidden;
|
||||
background-color:#989898;
|
||||
background-color: var(--area-background-color);
|
||||
border:1px solid #393939;
|
||||
border-color: var(--border-color);
|
||||
border-radius:3px;
|
||||
cursor:pointer;
|
||||
overflow:hidden;
|
||||
font-size: 12px;
|
||||
color:#333333;
|
||||
color:var(--text-color);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.layers_list .item.shorter .layer_name{
|
||||
width: calc(100% - 63px);
|
||||
}
|
||||
.layers_list .item.active .layer_name{
|
||||
background-color: #419147;
|
||||
background-color: var(--background-color-active);
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
.layers_list .arrow_down{
|
||||
position: relative;
|
||||
float:left;
|
||||
margin-right: 5px;
|
||||
width:10px;
|
||||
height:19px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.layers_list .arrow_down:after{
|
||||
position: absolute;
|
||||
content: '';
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
filter: var(--menu-icons-filter);
|
||||
background: url('images/icons/arrow-down.svg') no-repeat center center;
|
||||
background-size: 12px auto;
|
||||
}
|
||||
.layers_list .visibility{
|
||||
position: relative;
|
||||
float:left;
|
||||
cursor:pointer;
|
||||
padding:0px 3px 0px 3px;
|
||||
margin-right: 5px;
|
||||
width:20px;
|
||||
height:19px;
|
||||
background: url('images/sprites.png') no-repeat -148px -99px;
|
||||
opacity:0.1;
|
||||
border: none;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.layers_list .visibility:after{
|
||||
position: absolute;
|
||||
content: '';
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
filter: var(--menu-icons-filter);
|
||||
background: url('images/icons/view.svg') no-repeat center center;
|
||||
background-size: 18px auto;
|
||||
}
|
||||
.layers_list .visible{ opacity:0.4; }
|
||||
.layers_list .delete{
|
||||
@ -398,7 +487,10 @@
|
||||
width:12px;
|
||||
height:19px;
|
||||
margin-left: 5px;
|
||||
background: url('images/sprites.png') no-repeat -100px -96px;
|
||||
background: transparent url(images/icons/delete.svg) no-repeat center center;
|
||||
background-size: 10px 10px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
/* filters */
|
||||
.layers_list .filters{
|
||||
@ -420,74 +512,150 @@
|
||||
bottom:0;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.sidebar_right .label{
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
}
|
||||
.sidebar_right button.extra{
|
||||
border: 1px solid #444;
|
||||
background-color: var(--background-color-medium);
|
||||
}
|
||||
.info .toggle.toggled{
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.toggle-full.toggle.toggled{
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.block.details .row{
|
||||
clear:both;
|
||||
margin-bottom: 2px;
|
||||
margin-bottom: 4px;
|
||||
min-height: 23px;
|
||||
}
|
||||
.block.details input{
|
||||
.block.details input[type="number"]{
|
||||
width: 70px;
|
||||
padding: 3px 5px;
|
||||
float: right;
|
||||
}
|
||||
.block.details .ui_color_input{
|
||||
width: 70px;
|
||||
float: right;
|
||||
}
|
||||
.block.details .ui_color_input input{
|
||||
width: 100%;
|
||||
height: 23px;
|
||||
}
|
||||
.block.details button.ui_toggle_button{
|
||||
width: 90px;
|
||||
float: right;
|
||||
}
|
||||
.block.details select{
|
||||
width: calc(100% - 70px);
|
||||
height: 23px;
|
||||
float: right;
|
||||
}
|
||||
.block.details button{
|
||||
width: calc(100% - 70px);
|
||||
height: 23px;
|
||||
border: 1px solid #444;
|
||||
background-color: var(--background-color-medium);
|
||||
}
|
||||
.block.details button.reset{
|
||||
position: relative;
|
||||
width: 25px;
|
||||
float: right;
|
||||
margin-right: 3px;
|
||||
overflow: hidden;
|
||||
opacity: 0.3;
|
||||
background-image: url(images/sprites.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: -747px 2px;
|
||||
opacity: 0.5;
|
||||
color: transparent;
|
||||
}
|
||||
.block.details button.reset:after{
|
||||
position: absolute;
|
||||
content: '';
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
background: url(images/icons/refresh.svg) no-repeat center center;
|
||||
background-size: auto 14px;
|
||||
filter: var(--menu-icons-filter);
|
||||
}
|
||||
.block.details button.active{
|
||||
background-color: var(--background-color-active);
|
||||
background-color: var(--background-color-active);
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
.details-content{
|
||||
height: 206px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width:700px){
|
||||
body{
|
||||
padding-top:50px;
|
||||
}
|
||||
.wrapper{
|
||||
top: 50px;
|
||||
}
|
||||
.sidebar_left{
|
||||
position: absolute;
|
||||
left: -90px;
|
||||
background: var(--background);
|
||||
}
|
||||
.sidebar_left.active{
|
||||
box-shadow: -5px 0px 10px 0px rgba(0,0,0,0.75);
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
.sidebar_right{
|
||||
right: -200px;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
right: -210px;
|
||||
background: var(--background);
|
||||
}
|
||||
.sidebar_right.active{
|
||||
box-shadow: -5px 0px 10px 0px rgba(0,0,0,0.75);
|
||||
right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== content ======================================================= */
|
||||
|
||||
.ruler_left{
|
||||
display: none;
|
||||
position: absolute;
|
||||
left:0;
|
||||
top: 20px;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.ruler_top{
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top:0;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.middle_area{
|
||||
position: relative;
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 2;
|
||||
grid-area: main;
|
||||
}
|
||||
.main_wrapper{
|
||||
height: calc(100vh - 80px);
|
||||
margin: 5px 210px 5px 45px;
|
||||
position:absolute;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
left:0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.middle_area.has-ruler .main_wrapper{
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
}
|
||||
.canvas_wrapper{
|
||||
position:relative;
|
||||
}
|
||||
.canvas_wrapper canvas{
|
||||
position: absolute;
|
||||
border: 1px solid #393939;
|
||||
box-sizing: content-box;
|
||||
font-kerning: normal !important;
|
||||
}
|
||||
.loaded .canvas_wrapper canvas{
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
#mouse{
|
||||
position:absolute;
|
||||
@ -508,16 +676,10 @@
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
/*background: url(images/grid.png) repeat top left;*/
|
||||
/*background: url(images/icons/grid.png) repeat top left;*/
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAQElEQVQ4T2N89+7dfwYigKCgIBGqGBgYRw3EGU6jYYgzaIZAsvn//z9ROeX9+/fE5ZRRA3GG02gY4s4pgz7ZAAAnSWvHPkHXaAAAAABJRU5ErkJggg==') repeat top left;
|
||||
z-index:1;
|
||||
/* disable antialiasing */
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: pixelated; /* disable antialiasing */
|
||||
}
|
||||
.transparent-grid.white{
|
||||
background:white;
|
||||
@ -541,7 +703,7 @@ canvas{
|
||||
pointer-events:none;
|
||||
}
|
||||
.group{
|
||||
border:1px solid #888888;
|
||||
border:1px solid #999999;
|
||||
margin: 5px 0px 5px 0px;
|
||||
padding:5px 8px;
|
||||
}
|
||||
@ -558,17 +720,50 @@ canvas{
|
||||
height: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width:700px){
|
||||
body{
|
||||
padding-top:50px;
|
||||
}
|
||||
.main_wrapper{
|
||||
margin-right: 5px;
|
||||
}
|
||||
.alertify-notifier{
|
||||
color: black;
|
||||
}
|
||||
.effectsPreview{
|
||||
cursor: pointer;
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
@media screen and (max-width:550px){
|
||||
.canvas_wrapper{
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-height: 690px){
|
||||
.sidebar_left{
|
||||
width: 75px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-height:450px){
|
||||
.sidebar_left{
|
||||
width: 88px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== dialogs ======================================================= */
|
||||
|
||||
#dialog_color_picker_group {
|
||||
width: 60%;
|
||||
}
|
||||
#dialog_color_channel_group {
|
||||
width: 40%;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 450px) {
|
||||
#dialog_color_picker .ui_flex_group {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#dialog_color_picker_group {
|
||||
width: 100%;
|
||||
}
|
||||
#dialog_color_channel_group {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
374
src/css/menu.css
@ -1,214 +1,202 @@
|
||||
.mobile_menu{
|
||||
display:none;
|
||||
position: absolute;
|
||||
width:100%;
|
||||
top: 0;
|
||||
:root {
|
||||
--menu-dropdown-background-color: #ffffff;
|
||||
--menu-dropdown-border-color: #49844d;
|
||||
--menu-dropdown-text-color: #2d2b2b;
|
||||
--menu-dropdown-text-muted-color: #aaaaaa;
|
||||
--menu-dropdown-hover-background-color: #adecab;
|
||||
--menu-dropdown-hover-text-color: #2d2d2d;
|
||||
--menu-dropdown-divider-color: #e5e5e5;
|
||||
}
|
||||
.left_mobile_menu, .right_mobile_menu{
|
||||
position:absolute;
|
||||
width:50px;
|
||||
height:50px;
|
||||
background: url("images/sprites.png") no-repeat 11px -86px;
|
||||
filter: invert(1);
|
||||
display:block;
|
||||
top:0;
|
||||
z-index:200;
|
||||
border:0;
|
||||
outline:0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.left_mobile_menu{left:0;}
|
||||
.right_mobile_menu{right:0;}
|
||||
|
||||
.ddsmoothmenu{
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
font:12px Arial,sans-serif;
|
||||
background: #2D2D2D;
|
||||
width: 100%;
|
||||
padding-left:10px;
|
||||
z-index:100;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
z-index:100;
|
||||
margin: 0;
|
||||
.sr_only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
height:30px;
|
||||
}
|
||||
.ddsmoothmenu ul li{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
color: #2d2b2b;
|
||||
height:100%;
|
||||
}
|
||||
.ddsmoothmenu ul ul li a{
|
||||
width:100%;
|
||||
}
|
||||
.ddsmoothmenu .rightarrowclass{
|
||||
display:none !important;
|
||||
}
|
||||
.ddsmoothmenu ul li a{
|
||||
display: inline-block;
|
||||
color: #2D2D2D;
|
||||
text-decoration: none;
|
||||
color: #cccccc;
|
||||
text-align:center;
|
||||
padding: 7px 10px 8px 10px !important;
|
||||
}
|
||||
.ddsmoothmenu ul ul li a{
|
||||
padding-right: 25px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li a.selected{
|
||||
background-color: #FFFFFF !important;
|
||||
color: #2d2b2b;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a.selected{
|
||||
background-color:#E4EBF8 !important;
|
||||
}
|
||||
.ddsmoothmenu ul li a:hover{
|
||||
background-color: #E4EBF8;
|
||||
color: #2D2D2D;
|
||||
}
|
||||
.ddsmoothmenu .hide_ul{
|
||||
position: absolute;
|
||||
left: -3000px;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
border:1px solid #5680C1;
|
||||
border-top:0px;
|
||||
}
|
||||
.ddsmoothmenu ul li ul{
|
||||
position: absolute;
|
||||
left: -3000px;
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
border:1px solid #5680C1;
|
||||
border-top:0px;
|
||||
margin-left: -1px;
|
||||
height:auto;
|
||||
min-width:140px;
|
||||
width:auto !important;
|
||||
top:30px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li{
|
||||
display: list-item;
|
||||
background: #ffffff;
|
||||
float: none;
|
||||
height:auto;
|
||||
width:100%;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
text-align:left;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
top: 0;
|
||||
border-top:1px solid #5680C1;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
padding-left: 5px;
|
||||
padding-right:5px;
|
||||
margin: 0;
|
||||
color: #2D2D2D;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
top:0 !important;
|
||||
}
|
||||
.ddsmoothmenu .downarrowclass{
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 7px;
|
||||
}
|
||||
.ddsmoothmenu .ddshadow{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
.main_menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: #ccc;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.ddsmoothmenu .mid-line{
|
||||
background-color:#ff0000;
|
||||
border-top:1px solid #e5e5e5;
|
||||
font-size:0;
|
||||
padding:0 8px 0 8px;
|
||||
.main_menu > ul.menu_bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-left: 10px;
|
||||
background: var(--menu-background-color);
|
||||
}
|
||||
.ddsmoothmenu ul li ul li.more > a{
|
||||
position:relative;
|
||||
.main_menu > ul.menu_bar > li {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li.more > a:before{
|
||||
.main_menu > ul.menu_bar > li > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: var(--menu-text-color);
|
||||
text-decoration: none;
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
}
|
||||
.main_menu > ul.menu_bar > li > a::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
.main_menu > ul.menu_bar > li > a:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 -3px var(--menu-dropdown-background-color) inset;
|
||||
}
|
||||
.main_menu > ul.menu_bar > li > a:hover {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_bar > li > a[aria-expanded="true"] {
|
||||
background: var(--menu-dropdown-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_bar > li > a > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.main_menu > ul.menu_dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
min-width: 150px;
|
||||
box-shadow: 0 0 0 1px var(--menu-dropdown-border-color);
|
||||
background: var(--menu-dropdown-background-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li {
|
||||
padding: 0;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > hr {
|
||||
background: none;
|
||||
border: 1px solid var(--menu-dropdown-divider-color);
|
||||
border-bottom: none;
|
||||
margin: 0;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
text-decoration: none;
|
||||
color: var(--menu-dropdown-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > ::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px var(--menu-dropdown-hover-background-color) inset;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a:hover {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-expanded="true"] {
|
||||
background: var(--menu-dropdown-hover-background-color);
|
||||
box-shadow: none;
|
||||
color: var(--menu-dropdown-hover-text-color);
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-haspopup="true"]::after {
|
||||
position: absolute;
|
||||
content:">";
|
||||
content: ">";
|
||||
right: 9px;
|
||||
width: 5px;
|
||||
height: 14px;
|
||||
transform: scaleY(2);
|
||||
color: #808080;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li ul{
|
||||
left: calc(100% + 1px) !important;
|
||||
.main_menu > ul.menu_dropdown > li > a[aria-haspopup="true"] > .name {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.ddsmoothmenu .dots::after{
|
||||
content: " ...";
|
||||
.main_menu > ul.menu_dropdown > li > a[target="_blank"]::after {
|
||||
content: "";
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 5px;
|
||||
background: url('images/icons/external.png') no-repeat center center;
|
||||
background-size: auto 8px;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.ddsmoothmenu a[data-key]:after{
|
||||
position: absolute;
|
||||
content: attr(data-key) " ";
|
||||
color: #aaa;
|
||||
font-size: 12px;
|
||||
margin-left: 8px;
|
||||
right:10px;
|
||||
.main_menu > ul.menu_dropdown > li > a > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a > .name {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.main_menu > ul.menu_dropdown > li > a > .shortcut {
|
||||
flex-shrink: 1;
|
||||
color: var(--menu-dropdown-text-muted-color);
|
||||
}
|
||||
|
||||
@media screen and (max-width:700px){
|
||||
.mobile_menu{
|
||||
display:block;
|
||||
}
|
||||
.left_mobile_menu{
|
||||
display:none;
|
||||
}
|
||||
.ddsmoothmenu{
|
||||
height:50px;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
width: calc(100% - 50px);
|
||||
height:50px;
|
||||
}
|
||||
.ddsmoothmenu > ul > li > a{
|
||||
height:50px;
|
||||
padding-top: 15px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li ul{
|
||||
top:50px !important;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li{
|
||||
height:auto;
|
||||
}
|
||||
.ddsmoothmenu ul li ul li a{
|
||||
height:30px;
|
||||
}
|
||||
|
||||
.mobile_menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
}
|
||||
@media screen and (max-width:550px){
|
||||
.ddsmoothmenu{
|
||||
padding-left:0;
|
||||
}
|
||||
.ddsmoothmenu ul{
|
||||
width: calc(100% - 50px);
|
||||
}
|
||||
.ddsmoothmenu > ul > li{
|
||||
width: calc(100% / 7);
|
||||
}
|
||||
.ddsmoothmenu > ul > li > a{
|
||||
width:100%;
|
||||
padding-left: 3px !important;
|
||||
padding-right: 3px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left_mobile_menu{
|
||||
display:block;
|
||||
}
|
||||
.left_mobile_menu, .right_mobile_menu {
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: block;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
}
|
||||
.left_mobile_menu:after, .right_mobile_menu:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
left:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
filter: var(--mobile-menu-toggle-filter);
|
||||
background: url('images/icons/menu.svg') no-repeat center center;
|
||||
background-size: auto 26px;
|
||||
}
|
||||
.left_mobile_menu { left:0; }
|
||||
.right_mobile_menu { right:0; }
|
||||
|
||||
@media screen and (max-width:700px) {
|
||||
.mobile_menu {
|
||||
display: block;
|
||||
}
|
||||
.main_menu > ul.menu_bar {
|
||||
height: 50px;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
}
|
||||
@ -1,101 +1,271 @@
|
||||
#popup{
|
||||
#popups:not(:empty) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
#popups .popup {
|
||||
position:fixed;
|
||||
display:none;
|
||||
top: 20vh;
|
||||
left: calc(50% - 500px / 2);
|
||||
top: 15vh;
|
||||
left: calc(100vw / 2);
|
||||
transform: translate(-50%, 0);
|
||||
background-color: #7A838B;
|
||||
background-color: var(--block-background-color);
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid var(--background-color-border);
|
||||
width:500px;
|
||||
max-width: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
width: 90vw;
|
||||
max-width: 500px;
|
||||
max-height: calc(80vh);
|
||||
margin:0px auto 0px auto;
|
||||
padding:10px;
|
||||
box-shadow: 0 0 20px rgba(0,0,0,0.5);
|
||||
padding: 4rem 0 5rem 0;
|
||||
box-shadow: 0 0 0 4000px rgba(0,0,0,0.3), 0 0 20px rgba(0,0,0,0.5);
|
||||
z-index: 100;
|
||||
overflow-y: auto;
|
||||
font-size: 13px;
|
||||
overflow-y: scroll;
|
||||
overflow: hidden;
|
||||
}
|
||||
#popup.wide{
|
||||
top: 15vh;
|
||||
width: 800px;
|
||||
left: calc(50% - 800px / 2);
|
||||
#popups .popup.wide{
|
||||
max-width: 840px;
|
||||
}
|
||||
#popup a{
|
||||
color: #000080;
|
||||
#popups .popup a{
|
||||
color: var(--link-color);
|
||||
}
|
||||
#popup h2{
|
||||
margin: -10px -10px 5px -10px;
|
||||
padding: 6px 10px;
|
||||
font-size: 18px;
|
||||
#popups .popup h2{
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
height: 4rem;
|
||||
line-height: 4rem;
|
||||
padding: 0 1rem;
|
||||
font-size: 1.8rem;
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
background-color: var(--background-color-light);
|
||||
/*cursor:move;*/
|
||||
background-color: var(--header-background-color);
|
||||
z-index: 0;
|
||||
cursor:move;
|
||||
}
|
||||
#popup .buttons{
|
||||
text-align:center;
|
||||
margin-top:20px;
|
||||
margin-bottom:5px;
|
||||
#popups .popup .dialog_content {
|
||||
overflow-y: auto;
|
||||
max-height: calc(80vh - 11rem);
|
||||
padding: 1rem;
|
||||
}
|
||||
#popup td, #popup th{
|
||||
#popups .popup .buttons{
|
||||
position: absolute;
|
||||
background-color: var(--block-background-color);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 5rem;
|
||||
line-height: 4rem;
|
||||
margin: 0;
|
||||
padding: .5rem 0;
|
||||
text-align: center;
|
||||
border-top: 1px solid var(--header-background-color);
|
||||
z-index: 3;
|
||||
}
|
||||
#popups .popup .close{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
min-width: 0;
|
||||
padding: 5px;
|
||||
line-height: 0.5;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
border: none;
|
||||
background: none;
|
||||
z-index: 1;
|
||||
}
|
||||
#popups .popup input[type="range"]{
|
||||
margin:0;
|
||||
width: 100%;
|
||||
}
|
||||
#popups .popup table{
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
#popups .popup td, #popups .popup th{
|
||||
height: 25px;
|
||||
}
|
||||
#popup td{
|
||||
#popups .popup td{
|
||||
vertical-align: middle;
|
||||
}
|
||||
#popup th{
|
||||
#popups .popup th{
|
||||
text-align:left;
|
||||
padding: 5px 5px 5px 0;
|
||||
width: 130px;
|
||||
}
|
||||
#popup textarea{
|
||||
color:#000000;
|
||||
#popups .popup textarea{
|
||||
color: var(--input-text-color);
|
||||
width:100%;
|
||||
border:1px solid #393939;
|
||||
padding-left:5px;
|
||||
}
|
||||
#popup .button{
|
||||
#popups .popup .button{
|
||||
margin: 0 3px;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
background-color: var(--background-color-medium);
|
||||
background-color: var(--button-background-color);
|
||||
min-width:60px;
|
||||
border:1px solid rgba(0, 0, 0, 0.5);
|
||||
border:1px solid var(--background-color-border);
|
||||
border:1px solid var(--border-color);
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#popup input[type="text"], #popup input[type="number"], #popup textarea{
|
||||
#popups .popup input[type="text"], #popups .popup input[type="number"], #popups .popup textarea{
|
||||
width:100%;
|
||||
}
|
||||
#popup input[type="number"]{
|
||||
#popups .popup input[type="number"]{
|
||||
width:100px;
|
||||
}
|
||||
#popup input[type="radio"], #popup input[type="checkbox"]{
|
||||
#popups .popup input[type="radio"], #popups .popup input[type="checkbox"]{
|
||||
margin-left: 0;
|
||||
}
|
||||
#popup label span{
|
||||
color:#444444;
|
||||
#popups .popup label span{
|
||||
color:var(--text-color-muted);
|
||||
}
|
||||
#popup .checkbox label{
|
||||
#popups .popup .checkbox label{
|
||||
margin-top: 5px;
|
||||
color:#444444;
|
||||
color:var(--text-color-muted);
|
||||
}
|
||||
@media screen and (max-width:500px){
|
||||
#popup{
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
#canvas_preview_container{
|
||||
clear:both;
|
||||
}
|
||||
#popups .popup .preview_container{
|
||||
margin-top:10px;
|
||||
margin-bottom:15px;
|
||||
text-align: center;
|
||||
}
|
||||
@media screen and (max-height:650px){
|
||||
#popup{
|
||||
top: 0;
|
||||
max-height: 100vh;
|
||||
}
|
||||
#canvas_preview_container{
|
||||
clear:both;
|
||||
}
|
||||
#popups .popup .preview_canvas_left{
|
||||
position:relative;
|
||||
margin:0 5px 5px 0;
|
||||
border:1px solid #393939;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
#popups .popup .preview_canvas_post_back{
|
||||
position:absolute;
|
||||
border:1px solid #393939;
|
||||
background-color:#ffffff;
|
||||
}
|
||||
#popups .popup .preview_canvas_post{
|
||||
position:relative;
|
||||
border:1px solid #393939;
|
||||
}
|
||||
#popups .popup .canvas_preview_container{
|
||||
position:relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
#popups .popup .radios label{
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
#popups .popup .range_value{
|
||||
padding-left:10px;
|
||||
width:50px;
|
||||
}
|
||||
#popups .popup .long_text_value{
|
||||
font-size: 12px;
|
||||
}
|
||||
#popups .popup .preview-item-title{
|
||||
text-align: center;
|
||||
max-width: 150px;
|
||||
}
|
||||
#popups .popup .field_comment{
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#popups .popup .selection_card {
|
||||
background: var(--input-background-color);
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
border-bottom: 0.1rem solid var(--input-border-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
#popups .popup .selection_card:first-child {
|
||||
margin-top: 1rem;
|
||||
border-radius: var(--input-border-radius) var(--input-border-radius) 0 0;
|
||||
}
|
||||
#popups .popup .selection_card:last-child {
|
||||
border-radius: 0 0 var(--input-border-radius) var(--input-border-radius);
|
||||
border-bottom: none;
|
||||
}
|
||||
#popups .popup .selection_card > input[type="checkbox"] {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 1.5rem;
|
||||
transform: translateY(-50%) scale(1.5);
|
||||
}
|
||||
#popups .popup .selection_card > input[type="checkbox"] + label {
|
||||
display: block;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
margin: 0;
|
||||
padding: 1rem 0.5rem 1rem 5.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
#popups .popup .selection_card > input[type="checkbox"] + label:hover {
|
||||
background: var(--input-background-color-hover);
|
||||
}
|
||||
#popups .popup .selection_card .font_preview {
|
||||
font-size: 1.6rem;
|
||||
height: 2.5rem;
|
||||
line-height: 2.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#popups .popup .pagination {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
#popups .popup .pagination button {
|
||||
flex-grow: 0;
|
||||
height: 2.8rem;
|
||||
line-height: 2.8rem;
|
||||
border-radius: 0;
|
||||
margin-left: -1px;
|
||||
min-width: 3.3rem;
|
||||
}
|
||||
#popups .popup .pagination button:first-child {
|
||||
border-radius: var(--button-border-radius) 0 0 var(--button-border-radius);
|
||||
margin-left: auto;
|
||||
}
|
||||
#popups .popup .pagination button:last-child {
|
||||
border-radius: 0 var(--button-border-radius) var(--button-border-radius) 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width:500px){
|
||||
#popups .popup {
|
||||
max-height: calc(80vh - 20px); /* mobile phones has bottom menu */
|
||||
}
|
||||
#popups .popup tr{
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#popups .popup td, #popups .popup th{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 5px;
|
||||
}
|
||||
#popups .popup th{
|
||||
padding: 5px 5px 0px 5px;
|
||||
}
|
||||
#popups .popup td{
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
#popups .popup .range_value{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
.sidebar_left,
|
||||
.sidebar_right,
|
||||
.submenu,
|
||||
.ddsmoothmenu{
|
||||
.main_menu{
|
||||
display: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
@ -31,4 +31,4 @@
|
||||
.canvas_wrapper canvas{
|
||||
border:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,131 @@
|
||||
:root {
|
||||
/* original - default */
|
||||
--background: #666d6f;
|
||||
--text-color: #f4f3f3;
|
||||
--text-color-muted: #c1c1c1;
|
||||
--text-color-red: #e38282;
|
||||
--text-color-green: #8bdb8b;
|
||||
--text-color-blue: #a4a4ff;
|
||||
--link-color: #9ffda5;
|
||||
--section-background-color: #323a3c;
|
||||
--area-background-color: #464d4f;
|
||||
--block-background-color: #464d4f;
|
||||
--header-background-color: #373d3f;
|
||||
--button-background-color: #2f3739;
|
||||
--button-background-color-hover: #75df72;
|
||||
--button-background-color-active: #4d5153;
|
||||
--button-shadow-color: rgba(0, 0, 0, 0.3);
|
||||
--button-text-color-active: #adecab;
|
||||
--button-border-radius: .4rem;
|
||||
--button-toggle-background-color: #575f62;
|
||||
--button-toggle-background-color-hover: #575f62;
|
||||
--input-background-color: #2f3739;
|
||||
--input-background-color-hover: #383f44;
|
||||
--input-text-color: #f4f3f3;
|
||||
--input-border-color: #0f0f0f;
|
||||
--input-border-color-active: #70996e;
|
||||
--input-border-radius: .4rem;
|
||||
--input-group-border-color: #323a3c;
|
||||
--menu-background-color: #222;
|
||||
--menu-icons-filter: invert(1);
|
||||
--menu-icons-filter-active: none;
|
||||
--menu-text-color: #cccccc;
|
||||
--number-input-arrow-width: 2rem;
|
||||
--background-color-active: #adecab;
|
||||
--background-color-hover: #575f62;
|
||||
--text-color-active: #215b2a;
|
||||
--border-color: #727677;
|
||||
--scrollbar-track-color: #464d4f;
|
||||
--scrollbar-thumb-color: #2f3739;
|
||||
--mobile-menu-toggle-filter: invert(1);
|
||||
}
|
||||
body.theme-light{
|
||||
/* light */
|
||||
--background: #f9f9fa;
|
||||
--text-color: #0c0c0d;
|
||||
--text-color-muted: #444444;
|
||||
--text-color-red: #bb2424;
|
||||
--text-color-green: #2b882b;
|
||||
--text-color-blue: #5454ca;
|
||||
--link-color: #000080;
|
||||
--section-background-color: #eaeaea;
|
||||
--area-background-color: #d9d9d9;
|
||||
--block-background-color: #eaeaea;
|
||||
--header-background-color: #dbdbdb;
|
||||
--button-background-color: #f9f9fa;
|
||||
--button-background-color-hover: #ddd;
|
||||
--button-background-color-active: #f3f3f3;
|
||||
--button-text-color-active: #59aed8;
|
||||
--button-shadow-color: rgba(0, 0, 0, 0.1);
|
||||
--button-toggle-background-color: #b7b7b7;
|
||||
--button-toggle-background-color-hover: #b7b7b7;
|
||||
--input-background-color: #ffffff;
|
||||
--input-background-color-hover: #ddd;
|
||||
--input-text-color: #0c0c0d;
|
||||
--input-border-color: #ccc;
|
||||
--input-border-color-active: #59aed8;
|
||||
--input-group-border-color: #c4c4c4;
|
||||
--menu-background-color: #eaeaea;
|
||||
--menu-icons-filter: none;
|
||||
--menu-icons-filter-active: invert(1);
|
||||
--menu-text-color: #333333;
|
||||
--menu-dropdown-hover-background-color: #a3dbf7;
|
||||
--menu-dropdown-border-color: #15439b;
|
||||
--background-color-active: #a3dbf7;
|
||||
--background-color-hover: #c4c4c4;
|
||||
--text-color-active: #15439b;
|
||||
--border-color: #c1c1c1;
|
||||
--scrollbar-track-color: #f9f9fa;
|
||||
--scrollbar-thumb-color: #919090;
|
||||
--mobile-menu-toggle-filter: none;
|
||||
}
|
||||
body.theme-green{
|
||||
/* green */
|
||||
--background: #050702;
|
||||
--text-color: #acc3a9;
|
||||
--text-color-muted: #80937d;
|
||||
--link-color: #9ffda5;
|
||||
--section-background-color: #1c2e04;
|
||||
--area-background-color: #3b5f11;
|
||||
--block-background-color: #3b5f11;
|
||||
--header-background-color: #2b460f;
|
||||
--button-background-color: #2e4a0d;
|
||||
--button-background-color-hover: #58960e;
|
||||
--button-background-color-active:#2b460f;
|
||||
--button-text-color-active: #ccc;
|
||||
--button-toggle-background-color: #243e05;
|
||||
--button-toggle-background-color-hover: #243e05;
|
||||
--input-background-color: #ffffff;
|
||||
--input-background-color-hover: #ddd;
|
||||
--input-text-color: #0c0c0d;
|
||||
--input-border-color: #ccc;
|
||||
--menu-background-color: #1c2e04;
|
||||
--menu-icons-filter: invert(1);
|
||||
--menu-icons-filter-active: none;
|
||||
--menu-text-color: #acc3a9;
|
||||
--background-color-active: #58960e;
|
||||
--background-color-hover: #58960e;
|
||||
--text-color-active: #acc3a9;
|
||||
--border-color: #4d6b1e;
|
||||
--scrollbar-track-color: #050702;
|
||||
--scrollbar-thumb-color: #80937d;
|
||||
--mobile-menu-toggle-filter: invert(1);
|
||||
}
|
||||
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
:root {
|
||||
/* default */
|
||||
--background-color: #424F5A;
|
||||
--background-color-medium: rgba(255, 255, 255, 0.2);
|
||||
--background-color-light: rgba(255, 255, 255, 0.3);
|
||||
--background-color-lightest: rgba(255, 255, 255, 0.5);
|
||||
--background-color-border: rgba(0, 0, 0, 0.5);
|
||||
--background-color-active: #419147;
|
||||
--text-color: #000000;
|
||||
html {
|
||||
font-size: 10px; /* Base is 10px for easy REM calculation */
|
||||
}
|
||||
body{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
padding-top: 30px;
|
||||
margin: 0;
|
||||
padding: 30px 0 0 0;
|
||||
background-color: #424F5A;
|
||||
background-color: var(--background-color);
|
||||
font-size: 13px;
|
||||
background: var(--background);
|
||||
font-size: 1.3rem;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
color: #000000;
|
||||
color: var(--text-color);
|
||||
line-height: 1.4;
|
||||
font-weight: normal;
|
||||
@ -30,19 +135,9 @@ canvas{
|
||||
outline: none;
|
||||
/* disable select canvas */
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||
/* disable antialiasing */
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
}
|
||||
img{
|
||||
border: none;
|
||||
@ -63,8 +158,11 @@ hr{
|
||||
border-color: rgba(0,0,0,0.3);
|
||||
border-bottom: 0;
|
||||
}
|
||||
input[type="text"], input[type="button"], select, input[type="number"], textarea{
|
||||
border:1px solid #393939;
|
||||
input[type="text"], select, input[type="number"], textarea{
|
||||
background: var(--input-background-color);
|
||||
border: 1px solid var(--input-border-color);
|
||||
border-radius: var(--input-border-radius);
|
||||
color: var(--input-text-color);
|
||||
padding: 3px 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
@ -75,17 +173,33 @@ select{
|
||||
padding: 2px 4px;
|
||||
}
|
||||
input[type="range"]{
|
||||
margin-left:0px;
|
||||
margin-left: 0;
|
||||
width:100%;
|
||||
}
|
||||
input[type="button"]{
|
||||
background: #dddddd;
|
||||
button, input[type="button"]{
|
||||
border-radius: var(--button-border-radius);
|
||||
box-shadow: 0 1px 2px 0 var(--button-shadow-color), 0 1px 0 0 rgba(255, 255, 255, 0.1) inset;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--button-background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
input[type="button"]:disabled{
|
||||
button:hover, input[type="button"]:hover{
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
button:disabled, input[type="button"]:disabled{
|
||||
visibility:hidden;
|
||||
}
|
||||
button{
|
||||
cursor: pointer;
|
||||
button[aria-pressed="true"], input[type="button"][aria-pressed="true"]{
|
||||
background-color: var(--button-background-color-active);
|
||||
color: var(--button-text-color-active);
|
||||
box-shadow: 0 1px 2px 0 var(--button-shadow-color), 0 1px 1px 1.5px rgba(58, 40, 40, 0.1) inset, 0 -1px 0 0 var(--button-text-color-active) inset;
|
||||
}
|
||||
button[aria-pressed="true"]:hover, input[type="button"][aria-pressed="true"]:hover{
|
||||
background-color: var(--button-background-color-hover);
|
||||
}
|
||||
button.ui_toggle_button:hover{
|
||||
background-color: var(--button-toggle-background-color-hover);
|
||||
}
|
||||
label{
|
||||
display: inline-block;
|
||||
@ -110,6 +224,7 @@ label{
|
||||
@supports not (zoom:2) {
|
||||
input[type="radio"], input[type=checkbox]{
|
||||
transform: scale(1.5);
|
||||
margin: 8px;
|
||||
transform-origin: left center;
|
||||
margin: 8px 12px 8px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
src/css/utility.css
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
/* Common input label sizes */
|
||||
.label_width_character {
|
||||
width: 100%;
|
||||
max-width: 2.88rem;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.label_width_small {
|
||||
width: 100%;
|
||||
max-width: 6.4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.label_width_medium {
|
||||
width: 100%;
|
||||
max-width: 10.4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Font color utility */
|
||||
.text_red { color: var(--text-color-red); }
|
||||
.text_green { color: var(--text-color-green); }
|
||||
.text_blue { color: var(--text-color-blue); }
|
||||
.text_muted { color: var(--text-color-muted); }
|
||||
|
||||
/*
|
||||
Size inputs based on the number of "w" characters that could fit in the input. "w" is usually the widest character.
|
||||
This is a rough estimate since all characters vary in width. For example an input with numbers
|
||||
usually fits way more characters than an input with letters.
|
||||
"cw" means character width
|
||||
*/
|
||||
.input_cw_1, .input_cw_2, .input_cw_3, .input_cw_4, .input_cw_5,
|
||||
.input_cw_6, .input_cw_7, .input_cw_8, .input_cw_9, .input_cw_10
|
||||
.input_cw_11, .input_cw_12, .input_cw_13, .input_cw_14, .input_cw_15 {
|
||||
width: 100%;
|
||||
}
|
||||
.input_cw_1 { max-width: 2.25rem; }
|
||||
.input_cw_2 { max-width: 3.25rem; }
|
||||
.input_cw_3 { max-width: 4.25rem; }
|
||||
.input_cw_4 { max-width: 5.25rem; }
|
||||
.input_cw_5 { max-width: 6.25rem; }
|
||||
.input_cw_6 { max-width: 7.25rem; }
|
||||
.input_cw_7 { max-width: 8.25rem; }
|
||||
.input_cw_8 { max-width: 9.25rem; }
|
||||
.input_cw_9 { max-width: 10.25rem; }
|
||||
.input_cw_10 { max-width: 11.25rem; }
|
||||
.input_cw_11 { max-width: 12.25rem; }
|
||||
.input_cw_12 { max-width: 13.25rem; }
|
||||
.input_cw_13 { max-width: 14.25rem; }
|
||||
.input_cw_14 { max-width: 15.25rem; }
|
||||
.input_cw_15 { max-width: 16.25rem; }
|
||||
input[type="number"].input_cw_1 { max-width: 4.25rem; }
|
||||
input[type="number"].input_cw_2 { max-width: 5.25rem; }
|
||||
input[type="number"].input_cw_3 { max-width: 6.25rem; }
|
||||
input[type="number"].input_cw_4 { max-width: 7.25rem; }
|
||||
input[type="number"].input_cw_5 { max-width: 8.25rem; }
|
||||
input[type="number"].input_cw_6 { max-width: 9.25rem; }
|
||||
input[type="number"].input_cw_7 { max-width: 10.25rem; }
|
||||
input[type="number"].input_cw_8 { max-width: 11.25rem; }
|
||||
input[type="number"].input_cw_9 { max-width: 12.25rem; }
|
||||
input[type="number"].input_cw_10 { max-width: 13.25rem; }
|
||||
input[type="number"].input_cw_11 { max-width: 14.25rem; }
|
||||
input[type="number"].input_cw_12 { max-width: 15.25rem; }
|
||||
input[type="number"].input_cw_13 { max-width: 16.25rem; }
|
||||
input[type="number"].input_cw_14 { max-width: 17.25rem; }
|
||||
input[type="number"].input_cw_15 { max-width: 18.25rem; }
|
||||
.ui_number_input.input_cw_1 { max-width: calc(2.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_2 { max-width: calc(3.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_3 { max-width: calc(4.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_4 { max-width: calc(5.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_5 { max-width: calc(6.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_6 { max-width: calc(7.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_7 { max-width: calc(8.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_8 { max-width: calc(9.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_9 { max-width: calc(10.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_10 { max-width: calc(11.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_11 { max-width: calc(12.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_12 { max-width: calc(13.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_13 { max-width: calc(14.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_14 { max-width: calc(15.25rem + var(--number-input-arrow-width)); }
|
||||
.ui_number_input.input_cw_15 { max-width: calc(16.25rem + var(--number-input-arrow-width)); }
|
||||
5
src/js/actions/_README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Managing Undo History with Actions
|
||||
|
||||
More information on wiki page:
|
||||
|
||||
https://github.com/viliusle/miniPaint/wiki/Undo-Redo-system
|
||||
145
src/js/actions/activate-tool.js
Normal file
@ -0,0 +1,145 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
import alertify from './../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
export class Activate_tool_action extends Base_action {
|
||||
/**
|
||||
* Groups multiple actions together in the undo/redo history, runs them all at once.
|
||||
*/
|
||||
constructor(key, ignore_same_tool) {
|
||||
super('activate_tool', 'Activate Tool');
|
||||
this.ignore_same_tool = !!ignore_same_tool;
|
||||
this.key = key;
|
||||
this.old_key = null;
|
||||
this.tool_leave_actions = null;
|
||||
this.tool_activate_actions = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const key = this.key;
|
||||
this.old_key = app.GUI.GUI_tools.active_tool;
|
||||
|
||||
if (this.key !== this.old_key || this.ignore_same_tool) {
|
||||
|
||||
//reset last
|
||||
document.querySelector('#tools_container .' + this.old_key).classList.remove("active");
|
||||
|
||||
//send exit event to old previous tool
|
||||
if (config.TOOL.on_leave != undefined) {
|
||||
var moduleKey = config.TOOL.name;
|
||||
var functionName = config.TOOL.on_leave;
|
||||
this.tool_leave_actions = app.GUI.GUI_tools.tools_modules[moduleKey].object[functionName]();
|
||||
if (this.tool_leave_actions) {
|
||||
for (let action of this.tool_leave_actions) {
|
||||
await action.do();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//change active
|
||||
app.GUI.GUI_tools.active_tool = key;
|
||||
document.querySelector('#tools_container .' + app.GUI.GUI_tools.active_tool)
|
||||
.classList.add("active");
|
||||
for (let i in config.TOOLS) {
|
||||
if (config.TOOLS[i].name == app.GUI.GUI_tools.active_tool) {
|
||||
config.TOOL = config.TOOLS[i];
|
||||
}
|
||||
}
|
||||
|
||||
//check module
|
||||
if (app.GUI.GUI_tools.tools_modules[key] == undefined) {
|
||||
alertify.error('Tools class not found: ' + key);
|
||||
return;
|
||||
}
|
||||
|
||||
//set default cursor
|
||||
const mainWrapper = document.getElementById('main_wrapper');
|
||||
const defaultCursor = config.TOOL && config.TOOL.name === 'text' ? 'text' : 'default';
|
||||
if (mainWrapper.style.cursor != defaultCursor) {
|
||||
mainWrapper.style.cursor = defaultCursor;
|
||||
}
|
||||
|
||||
app.GUI.GUI_tools.show_action_attributes();
|
||||
app.GUI.GUI_tools.Helper.setCookie('active_tool', app.GUI.GUI_tools.active_tool);
|
||||
}
|
||||
|
||||
//send activate event to new tool
|
||||
if (config.TOOL.on_activate != undefined) {
|
||||
var moduleKey = config.TOOL.name;
|
||||
var functionName = config.TOOL.on_activate;
|
||||
this.tool_activate_actions = app.GUI.GUI_tools.tools_modules[moduleKey].object[functionName]();
|
||||
if (this.tool_activate_actions) {
|
||||
for (let action of this.tool_activate_actions) {
|
||||
await action.do();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
|
||||
// Undo activate actions
|
||||
if (this.tool_activate_actions) {
|
||||
for (let action of this.tool_activate_actions) {
|
||||
await action.undo();
|
||||
action.free();
|
||||
}
|
||||
this.tool_activate_actions = null;
|
||||
}
|
||||
|
||||
//reset last
|
||||
document.querySelector('#tools_container .' + this.key)
|
||||
.classList.remove("active");
|
||||
|
||||
//change active
|
||||
app.GUI.GUI_tools.active_tool = this.old_key;
|
||||
document.querySelector('#tools_container .' + app.GUI.GUI_tools.active_tool)
|
||||
.classList.add("active");
|
||||
for (let i in config.TOOLS) {
|
||||
if (config.TOOLS[i].name == app.GUI.GUI_tools.active_tool) {
|
||||
config.TOOL = config.TOOLS[i];
|
||||
}
|
||||
}
|
||||
|
||||
app.GUI.GUI_tools.show_action_attributes();
|
||||
app.GUI.GUI_tools.Helper.setCookie('active_tool', app.GUI.GUI_tools.active_tool);
|
||||
|
||||
//set default cursor
|
||||
const mainWrapper = document.getElementById('main_wrapper');
|
||||
const defaultCursor = config.TOOL && config.TOOL.name === 'text' ? 'text' : 'default';
|
||||
if (mainWrapper.style.cursor != defaultCursor) {
|
||||
mainWrapper.style.cursor = defaultCursor;
|
||||
}
|
||||
|
||||
// Undo leave actions
|
||||
if (this.tool_leave_actions) {
|
||||
for (let action of this.tool_leave_actions) {
|
||||
await action.undo();
|
||||
action.free();
|
||||
}
|
||||
this.tool_leave_actions = null;
|
||||
}
|
||||
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
if (this.tool_activate_actions) {
|
||||
for (let action of this.tool_activate_actions) {
|
||||
action.free();
|
||||
}
|
||||
this.tool_activate_actions = null;
|
||||
}
|
||||
if (this.tool_leave_actions) {
|
||||
for (let action of this.tool_leave_actions) {
|
||||
action.free();
|
||||
}
|
||||
this.tool_leave_actions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/js/actions/add-layer-filter.js
Normal file
@ -0,0 +1,67 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Add_layer_filter_action extends Base_action {
|
||||
/**
|
||||
* register new live filter
|
||||
*
|
||||
* @param {int} layer_id
|
||||
* @param {string} name
|
||||
* @param {object} params
|
||||
*/
|
||||
constructor(layer_id, name, params, filter_id) {
|
||||
super('add_layer_filter', 'Add Layer Filter');
|
||||
if (layer_id == null)
|
||||
layer_id = config.layer.id;
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.name = name;
|
||||
this.params = params;
|
||||
this.filter_id = filter_id;
|
||||
this.reference_layer = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
var filter = {
|
||||
id: this.filter_id,
|
||||
name: this.name,
|
||||
params: this.params,
|
||||
};
|
||||
if(this.filter_id) {
|
||||
//update
|
||||
for(var i in this.reference_layer.filters) {
|
||||
if(this.reference_layer.filters[i].id == this.filter_id){
|
||||
this.reference_layer.filters[i] = filter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//insert
|
||||
filter.id = Math.floor(Math.random() * 999999999) + 1; // A good UUID library would
|
||||
this.reference_layer.filters.push(filter);
|
||||
}
|
||||
config.need_render = true;
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.reference_layer) {
|
||||
this.reference_layer.filters.pop();
|
||||
this.reference_layer = null;
|
||||
}
|
||||
config.need_render = true;
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
this.reference_layer = null;
|
||||
this.params = null;
|
||||
}
|
||||
}
|
||||
100
src/js/actions/autoresize-canvas.js
Normal file
@ -0,0 +1,100 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
import Tools_settings_class from './../modules/tools/settings.js';
|
||||
|
||||
export class Autoresize_canvas_action extends Base_action {
|
||||
/**
|
||||
* autoresize canvas to layer size, based on dimensions, up - always, if 1 layer - down.
|
||||
*
|
||||
* @param {int} width
|
||||
* @param {int} height
|
||||
* @param {int} layer_id
|
||||
* @param {boolean} can_automate
|
||||
*/
|
||||
constructor(width, height, layer_id, can_automate = true, ignore_same_size = false) {
|
||||
super('autoresize_canvas', 'Auto-resize Canvas');
|
||||
this.Tools_settings = new Tools_settings_class();
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.layer_id = layer_id;
|
||||
this.can_automate = can_automate;
|
||||
this.ignore_same_size = ignore_same_size;
|
||||
this.old_config_width = null;
|
||||
this.old_config_height = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const width = this.width;
|
||||
const height = this.height;
|
||||
const can_automate = this.can_automate;
|
||||
let need_fit = false;
|
||||
let new_config_width = config.WIDTH;
|
||||
let new_config_height = config.HEIGHT;
|
||||
var enable_autoresize = this.Tools_settings.get_setting('enable_autoresize');
|
||||
|
||||
if(enable_autoresize == false){
|
||||
return;
|
||||
}
|
||||
|
||||
// Resize up
|
||||
if (width > new_config_width || height > new_config_height) {
|
||||
const wrapper = document.getElementById('main_wrapper');
|
||||
const page_w = wrapper.clientWidth;
|
||||
const page_h = wrapper.clientHeight;
|
||||
|
||||
if (width > page_w || height > page_h) {
|
||||
need_fit = true;
|
||||
}
|
||||
if (width > new_config_width)
|
||||
new_config_width = parseInt(width);
|
||||
if (height > new_config_height)
|
||||
new_config_height = parseInt(height);
|
||||
}
|
||||
|
||||
// Resize down
|
||||
if (config.layers.length == 1 && can_automate !== false) {
|
||||
if (width < new_config_width)
|
||||
new_config_width = parseInt(width);
|
||||
if (height < new_config_height)
|
||||
new_config_height = parseInt(height);
|
||||
}
|
||||
|
||||
if (new_config_width !== config.WIDTH || new_config_height !== height) {
|
||||
this.old_config_width = config.WIDTH;
|
||||
this.old_config_height = config.HEIGHT;
|
||||
config.WIDTH = new_config_width;
|
||||
config.HEIGHT = new_config_height;
|
||||
app.GUI.prepare_canvas();
|
||||
} else if (!this.ignore_same_size) {
|
||||
throw new Error('Aborted - Resize not necessary')
|
||||
}
|
||||
|
||||
// Fit zoom when after short pause
|
||||
// @todo - remove setTimeout
|
||||
if (need_fit == true) {
|
||||
await new Promise((resolve) => {
|
||||
window.setTimeout(() => {
|
||||
app.GUI.GUI_preview.zoom_auto();
|
||||
resolve();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.old_config_width != null) {
|
||||
config.WIDTH = this.old_config_width;
|
||||
}
|
||||
if (this.old_config_height != null) {
|
||||
config.HEIGHT = this.old_config_height;
|
||||
}
|
||||
if (this.old_config_width != null || this.old_config_height != null) {
|
||||
app.GUI.prepare_canvas();
|
||||
}
|
||||
this.old_config_width = null;
|
||||
this.old_config_height = null;
|
||||
}
|
||||
}
|
||||
19
src/js/actions/base.js
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
export class Base_action {
|
||||
constructor(action_id, action_description) {
|
||||
this.action_id = action_id;
|
||||
this.action_description = action_description;
|
||||
this.is_done = false;
|
||||
this.memory_estimate = 0; // Estimate of how much memory will be freed when the free() method is called (in bytes)
|
||||
this.database_estimate = 0; // Estimate of how much database space will be freed when the free() method is called (in bytes)
|
||||
}
|
||||
do() {
|
||||
this.is_done = true;
|
||||
}
|
||||
undo() {
|
||||
this.is_done = false;
|
||||
}
|
||||
free() {
|
||||
// Override if need to run tasks to free memory when action is discarded from history
|
||||
}
|
||||
}
|
||||
59
src/js/actions/bundle.js
Normal file
@ -0,0 +1,59 @@
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Bundle_action extends Base_action {
|
||||
/**
|
||||
* Groups multiple actions together in the undo/redo history, runs them all at once.
|
||||
*/
|
||||
constructor(bundle_id, bundle_name, actions_to_do) {
|
||||
super(bundle_id, bundle_name);
|
||||
this.actions_to_do = actions_to_do;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
let error = null;
|
||||
let i = 0;
|
||||
this.memory_estimate = 0;
|
||||
this.database_estimate = 0;
|
||||
for (i = 0; i < this.actions_to_do.length; i++) {
|
||||
try {
|
||||
await this.actions_to_do[i].do();
|
||||
this.memory_estimate += this.actions_to_do[i].memory_estimate;
|
||||
this.database_estimate += this.actions_to_do[i].database_estimate;
|
||||
} catch (e) {
|
||||
error = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// One of the actions aborted, undo all previous actions.
|
||||
if (error) {
|
||||
for (i--; i >= 0; i--) {
|
||||
await this.actions_to_do[i].undo();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
this.memory_estimate = 0;
|
||||
this.database_estimate = 0;
|
||||
for (let i = this.actions_to_do.length - 1; i >= 0; i--) {
|
||||
await this.actions_to_do[i].undo();
|
||||
this.memory_estimate += this.actions_to_do[i].memory_estimate;
|
||||
this.database_estimate += this.actions_to_do[i].database_estimate;
|
||||
}
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
if (this.actions_to_do) {
|
||||
for (let action of this.actions_to_do) {
|
||||
action.free();
|
||||
}
|
||||
this.actions_to_do = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
src/js/actions/clear-layer.js
Normal file
@ -0,0 +1,82 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Clear_layer_action extends Base_action {
|
||||
/**
|
||||
* clear layer data
|
||||
*
|
||||
* @param {int} layer_id
|
||||
*/
|
||||
constructor(layer_id) {
|
||||
super('clear_layer', 'Clear Layer');
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.update_layer_action = null;
|
||||
this.delete_layer_settings_action = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
let layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
let new_settings = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
visible: true,
|
||||
opacity: 100,
|
||||
composition: null,
|
||||
rotate: 0,
|
||||
data: null,
|
||||
params: {},
|
||||
status: null,
|
||||
render_function: null,
|
||||
type: null
|
||||
};
|
||||
if (layer.type == 'image') {
|
||||
//clean image
|
||||
new_settings.link = null;
|
||||
}
|
||||
this.update_layer_action = new app.Actions.Update_layer_action(this.layer_id, new_settings);
|
||||
await this.update_layer_action.do();
|
||||
let delete_setting_names = [];
|
||||
for (let prop_name in layer) {
|
||||
//remove private attributes
|
||||
if (prop_name[0] == '_') {
|
||||
delete_setting_names.push(prop_name);
|
||||
}
|
||||
}
|
||||
if (delete_setting_names.length > 0) {
|
||||
this.delete_layer_settings_action = new app.Actions.Delete_layer_settings_action(this.layer_id, delete_setting_names);
|
||||
await this.delete_layer_settings_action.do();
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.delete_layer_settings_action) {
|
||||
await this.delete_layer_settings_action.undo();
|
||||
this.delete_layer_settings_action.free();
|
||||
this.delete_layer_settings_action = null;
|
||||
}
|
||||
if (this.update_layer_action) {
|
||||
await this.update_layer_action.undo();
|
||||
this.update_layer_action.free();
|
||||
this.update_layer_action = null;
|
||||
}
|
||||
}
|
||||
|
||||
free() {
|
||||
if (this.update_layer_action) {
|
||||
this.update_layer_action.free();
|
||||
this.update_layer_action = null;
|
||||
}
|
||||
if (this.delete_layer_settings_action) {
|
||||
this.delete_layer_settings_action.free();
|
||||
this.delete_layer_settings_action = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/js/actions/delete-layer-filter.js
Normal file
@ -0,0 +1,60 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Delete_layer_filter_action extends Base_action {
|
||||
/**
|
||||
* delete live filter
|
||||
*
|
||||
* @param {int} layer_id
|
||||
* @param {string} filter_id
|
||||
*/
|
||||
constructor(layer_id, filter_id) {
|
||||
super('delete_layer_filter', 'Delete Layer Filter');
|
||||
if (layer_id == null)
|
||||
layer_id = config.layer.id;
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.filter_id = filter_id;
|
||||
this.reference_layer = null;
|
||||
this.filter_remove_index = null;
|
||||
this.old_filter = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
this.old_filter = null;
|
||||
for (let i in this.reference_layer.filters) {
|
||||
if (this.reference_layer.filters[i].id == this.filter_id) {
|
||||
this.filter_remove_index = i;
|
||||
this.old_filter = this.reference_layer.filters.splice(i, 1)[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!this.old_filter) {
|
||||
throw new Error('Aborted - filter with specified id doesn\'t exist in layer');
|
||||
}
|
||||
config.need_render = true;
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.reference_layer && this.old_filter) {
|
||||
this.reference_layer.filters.splice(this.filter_remove_index, 0, this.old_filter);
|
||||
}
|
||||
this.reference_layer = null;
|
||||
this.old_filter = null;
|
||||
this.filter_remove_index = null;
|
||||
config.need_render = true;
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
this.reference_layer = null;
|
||||
this.old_filter = null;
|
||||
}
|
||||
}
|
||||
50
src/js/actions/delete-layer-settings.js
Normal file
@ -0,0 +1,50 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Delete_layer_settings_action extends Base_action {
|
||||
/**
|
||||
* Deletes the specified settings in a layer
|
||||
*
|
||||
* @param {int} layer_id
|
||||
* @param {array} setting_names
|
||||
*/
|
||||
constructor(layer_id, setting_names) {
|
||||
super('delete_layer_settings', 'Delete Layer Settings');
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.setting_names = setting_names;
|
||||
this.reference_layer = null;
|
||||
this.old_settings = {};
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
for (let name in this.setting_names) {
|
||||
this.old_settings[name] = this.reference_layer[name];
|
||||
delete this.reference_layer[name];
|
||||
}
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.reference_layer) {
|
||||
for (let i in this.old_settings) {
|
||||
this.reference_layer[i] = this.old_settings[i];
|
||||
}
|
||||
this.old_settings = {};
|
||||
}
|
||||
this.reference_layer = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.setting_names = null;
|
||||
this.reference_layer = null;
|
||||
this.old_settings = null;
|
||||
}
|
||||
}
|
||||
115
src/js/actions/delete-layer.js
Normal file
@ -0,0 +1,115 @@
|
||||
import config from '../config.js';
|
||||
import app from './../app.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Delete_layer_action extends Base_action {
|
||||
/**
|
||||
* removes layer
|
||||
*
|
||||
* @param {int} id
|
||||
* @param {boolean} force - Force to delete first layer?
|
||||
*/
|
||||
constructor(layer_id, force) {
|
||||
super('delete_layer', 'Delete Layer');
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.force = force || false;
|
||||
this.insert_layer_action = null;
|
||||
this.select_layer_action = null;
|
||||
this.delete_index = null;
|
||||
this.deleted_layer = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const id = this.layer_id;
|
||||
const force = this.force;
|
||||
|
||||
// Determine if there is a layer to delete, abort if not
|
||||
for (var i in config.layers) {
|
||||
if (config.layers[i].id == id) {
|
||||
this.delete_index = i;
|
||||
}
|
||||
}
|
||||
if (this.delete_index === null) {
|
||||
throw new Error('Aborted - Layer to delete not found');
|
||||
}
|
||||
|
||||
if (config.layers.length == 1 && (force == undefined || force == false)) {
|
||||
// Only 1 layer left
|
||||
if (config.layer.type == null) {
|
||||
//STOP
|
||||
throw new Error('Aborted - Will not delete last layer');
|
||||
}
|
||||
else {
|
||||
// Delete it, but before that - create new empty layer
|
||||
this.insert_layer_action = new app.Actions.Insert_layer_action();
|
||||
this.insert_layer_action.do();
|
||||
}
|
||||
}
|
||||
|
||||
if (config.layers.length > 1 && config.layer.id == id) {
|
||||
// Select next or previous layer
|
||||
try {
|
||||
const select_action = new app.Actions.Select_next_layer_action(id);
|
||||
await select_action.do();
|
||||
this.select_layer_action = select_action;
|
||||
} catch (error) {
|
||||
const select_action = new app.Actions.Select_previous_layer_action(id);
|
||||
await select_action.do();
|
||||
this.select_layer_action = select_action;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove layer from list
|
||||
this.deleted_layer = config.layers.splice(this.delete_index, 1)[0];
|
||||
|
||||
// Estimate memory
|
||||
if (this.deleted_layer.link && this.deleted_layer.link.src && typeof this.deleted_layer.link.src === 'string') {
|
||||
this.memory_estimate = new Blob([this.deleted_layer.link.src]).size;
|
||||
}
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.deleted_layer) {
|
||||
config.layers.splice(this.delete_index, 0, this.deleted_layer);
|
||||
this.delete_index = null;
|
||||
this.deleted_layer = null;
|
||||
}
|
||||
if (this.select_layer_action) {
|
||||
await this.select_layer_action.undo();
|
||||
this.select_layer_action.free();
|
||||
this.select_layer_action = null;
|
||||
}
|
||||
if (this.insert_layer_action) {
|
||||
await this.insert_layer_action.undo();
|
||||
this.insert_layer_action.free();
|
||||
this.insert_layer_action = null;
|
||||
}
|
||||
|
||||
// Estimate memory
|
||||
this.memory_estimate = 0;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
if (this.deleted_layer) {
|
||||
delete this.deleted_layer.link;
|
||||
delete this.deleted_layer.data;
|
||||
}
|
||||
if (this.insert_layer_action) {
|
||||
this.insert_layer_action.free();
|
||||
this.insert_layer_action = null;
|
||||
}
|
||||
if (this.select_layer_action) {
|
||||
this.select_layer_action.free();
|
||||
this.select_layer_action = null;
|
||||
}
|
||||
this.deleted_layer = null;
|
||||
}
|
||||
}
|
||||
26
src/js/actions/index.js
Normal file
@ -0,0 +1,26 @@
|
||||
export { Activate_tool_action } from './activate-tool.js';
|
||||
export { Add_layer_filter_action } from './add-layer-filter.js';
|
||||
export { Autoresize_canvas_action } from './autoresize-canvas.js';
|
||||
export { Bundle_action } from './bundle.js';
|
||||
export { Clear_layer_action } from './clear-layer.js';
|
||||
export { Delete_layer_action } from './delete-layer.js';
|
||||
export { Delete_layer_filter_action } from './delete-layer-filter.js';
|
||||
export { Delete_layer_settings_action } from './delete-layer-settings.js';
|
||||
export { Init_canvas_zoom_action } from './init-canvas-zoom.js';
|
||||
export { Insert_layer_action } from './insert-layer.js';
|
||||
export { Prepare_canvas_action } from './prepare-canvas.js';
|
||||
export { Reorder_layer_action } from './reorder-layer.js';
|
||||
export { Reset_layers_action } from './reset-layers.js';
|
||||
export { Refresh_action_attributes_action } from './refresh-action-attributes.js';
|
||||
export { Refresh_layers_gui_action } from './refresh-layers-gui.js';
|
||||
export { Reset_selection_action } from './reset-selection.js';
|
||||
export { Select_layer_action } from './select-layer.js';
|
||||
export { Select_next_layer_action } from './select-next-layer.js';
|
||||
export { Select_previous_layer_action } from './select-previous-layer.js';
|
||||
export { Set_object_property_action } from './set-object-property.js';
|
||||
export { Set_selection_action } from './set-selection.js';
|
||||
export { Stop_animation_action } from './stop-animation.js';
|
||||
export { Toggle_layer_visibility_action } from './toggle-layer-visibility.js';
|
||||
export { Update_config_action } from './update-config.js';
|
||||
export { Update_layer_image_action } from './update-layer-image.js';
|
||||
export { Update_layer_action } from './update-layer.js';
|
||||
45
src/js/actions/init-canvas-zoom.js
Normal file
@ -0,0 +1,45 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import zoomView from '../libs/zoomView.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Init_canvas_zoom_action extends Base_action {
|
||||
/**
|
||||
* Resets the canvas
|
||||
*/
|
||||
constructor() {
|
||||
super('init_canvas_zoom', 'Initialize Canvas Zoom');
|
||||
this.old_bounds = null;
|
||||
this.old_context = null;
|
||||
this.old_stable_dimensions = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.old_bounds = zoomView.getBounds();
|
||||
this.old_context = zoomView.getContext();
|
||||
this.old_stable_dimensions = app.Layers.stable_dimensions;
|
||||
zoomView.setBounds(0, 0, config.WIDTH, config.HEIGHT);
|
||||
zoomView.setContext(app.Layers.ctx);
|
||||
app.Layers.stable_dimensions = [
|
||||
config.WIDTH,
|
||||
config.HEIGHT
|
||||
];
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
zoomView.setBounds(this.old_bounds.top, this.old_bounds.left, this.old_bounds.right, this.old_bounds.bottom);
|
||||
zoomView.setContext(this.old_context);
|
||||
app.Layers.stable_dimensions = this.old_stable_dimensions;
|
||||
this.old_bounds = null;
|
||||
this.old_context = null;
|
||||
this.old_stable_dimensions = null;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.old_bounds = null;
|
||||
this.old_context = null;
|
||||
this.old_stable_dimensions = null;
|
||||
}
|
||||
}
|
||||
214
src/js/actions/insert-layer.js
Normal file
@ -0,0 +1,214 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
import alertify from './../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
|
||||
export class Insert_layer_action extends Base_action {
|
||||
/**
|
||||
* Creates new layer
|
||||
*
|
||||
* @param {object} settings
|
||||
* @param {boolean} can_automate
|
||||
*/
|
||||
constructor(settings, can_automate = true) {
|
||||
super('insert_layer', 'Insert Layer');
|
||||
this.settings = settings;
|
||||
this.can_automate = can_automate;
|
||||
this.previous_auto_increment = null;
|
||||
this.previous_selected_layer = null;
|
||||
this.inserted_layer_id = null;
|
||||
this.update_layer_action = null;
|
||||
this.delete_layer_action = null;
|
||||
this.autoresize_canvas_action = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
|
||||
this.previous_auto_increment = app.Layers.auto_increment;
|
||||
this.previous_selected_layer = config.layer;
|
||||
let autoresize_as = null;
|
||||
|
||||
// Default data
|
||||
const layer = {
|
||||
id: app.Layers.auto_increment,
|
||||
parent_id: 0,
|
||||
name: config.TOOL.name.charAt(0).toUpperCase() + config.TOOL.name.slice(1) + ' #' + app.Layers.auto_increment,
|
||||
type: null,
|
||||
link: null,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: null,
|
||||
width_original: null,
|
||||
height: null,
|
||||
height_original: null,
|
||||
visible: true,
|
||||
is_vector: false,
|
||||
hide_selection_if_active: false,
|
||||
opacity: 100,
|
||||
order: app.Layers.auto_increment,
|
||||
composition: 'source-over',
|
||||
rotate: 0,
|
||||
data: null,
|
||||
params: {},
|
||||
status: null,
|
||||
color: config.COLOR,
|
||||
filters: [],
|
||||
render_function: null,
|
||||
};
|
||||
|
||||
// Build data
|
||||
for (let i in this.settings) {
|
||||
if (typeof layer[i] == "undefined" && !i.startsWith('_')) {
|
||||
alertify.error('Error: wrong key: ' + i);
|
||||
continue;
|
||||
}
|
||||
layer[i] = this.settings[i];
|
||||
}
|
||||
|
||||
// Prepare image
|
||||
let image_load_promise;
|
||||
if (layer.type == 'image') {
|
||||
|
||||
if(layer.name.toLowerCase().indexOf('.svg') == layer.name.length - 4){
|
||||
// We have svg
|
||||
layer.is_vector = true;
|
||||
}
|
||||
|
||||
if (config.layers.length == 1 && (config.layer.width == 0 || config.layer.width === null)
|
||||
&& (config.layer.height == 0 || config.layer.height === null) && config.layer.data == null) {
|
||||
// Remove first empty layer
|
||||
|
||||
this.delete_layer_action = new app.Actions.Delete_layer_action(config.layer.id, true);
|
||||
await this.delete_layer_action.do();
|
||||
}
|
||||
|
||||
if (layer.link == null) {
|
||||
if (typeof layer.data == 'object') {
|
||||
// Load actual image
|
||||
if (layer.width == 0 || layer.width === null)
|
||||
layer.width = layer.data.width;
|
||||
if (layer.height == 0 || layer.height === null)
|
||||
layer.height = layer.data.height;
|
||||
layer.link = layer.data.cloneNode(true);
|
||||
layer.link.onload = function () {
|
||||
config.need_render = true;
|
||||
};
|
||||
layer.data = null;
|
||||
autoresize_as = [layer.width, layer.height, null, true, true];
|
||||
//need_autoresize = true;
|
||||
}
|
||||
else if (typeof layer.data == 'string') {
|
||||
image_load_promise = new Promise((resolve, reject) => {
|
||||
// Try loading as imageData
|
||||
layer.link = new Image();
|
||||
layer.link.onload = () => {
|
||||
// Update dimensions
|
||||
if (layer.width == 0 || layer.width === null)
|
||||
layer.width = layer.link.width;
|
||||
if (layer.height == 0 || layer.height === null)
|
||||
layer.height = layer.link.height;
|
||||
if (layer.width_original == null)
|
||||
layer.width_original = layer.width;
|
||||
if (layer.height_original == null)
|
||||
layer.height_original = layer.height;
|
||||
// Free data
|
||||
layer.data = null;
|
||||
autoresize_as = [layer.width, layer.height, layer.id, this.can_automate, true];
|
||||
config.need_render = true;
|
||||
resolve();
|
||||
};
|
||||
layer.link.onerror = (error) => {
|
||||
resolve(error);
|
||||
alertify.error('Sorry, image could not be loaded.');
|
||||
};
|
||||
layer.link.src = layer.data;
|
||||
layer.link.crossOrigin = "Anonymous";
|
||||
});
|
||||
}
|
||||
else {
|
||||
alertify.error('Error: can not load image.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.settings != undefined && config.layers.length > 0
|
||||
&& (config.layer.width == 0 || config.layer.width === null) && (config.layer.height == 0 || config.layer.height === null)
|
||||
&& config.layer.data == null && layer.type != 'image' && this.can_automate !== false) {
|
||||
// Update existing layer, because it's empty
|
||||
this.update_layer_action = new app.Actions.Update_layer_action(config.layer.id, layer);
|
||||
await this.update_layer_action.do();
|
||||
}
|
||||
else {
|
||||
// Create new layer
|
||||
config.layers.push(layer);
|
||||
config.layer = app.Layers.get_layer(layer.id);
|
||||
app.Layers.auto_increment++;
|
||||
|
||||
if (config.layer == null) {
|
||||
config.layer = config.layers[0];
|
||||
}
|
||||
|
||||
this.inserted_layer_id = layer.id;
|
||||
}
|
||||
|
||||
if (layer.id >= app.Layers.auto_increment)
|
||||
app.Layers.auto_increment = layer.id + 1;
|
||||
|
||||
if (image_load_promise) {
|
||||
await image_load_promise;
|
||||
}
|
||||
|
||||
if (autoresize_as) {
|
||||
this.autoresize_canvas_action = new app.Actions.Autoresize_canvas_action(...autoresize_as);
|
||||
try {
|
||||
await this.autoresize_canvas_action.do();
|
||||
} catch(error) {
|
||||
this.autoresize_canvas_action = null;
|
||||
}
|
||||
}
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
app.Layers.auto_increment = this.previous_auto_increment;
|
||||
if (this.autoresize_canvas_action) {
|
||||
await this.autoresize_canvas_action.undo();
|
||||
this.autoresize_canvas_action = null;
|
||||
}
|
||||
if (this.inserted_layer_id) {
|
||||
config.layers.pop();
|
||||
this.inserted_layer_id = null;
|
||||
}
|
||||
if (this.update_layer_action) {
|
||||
await this.update_layer_action.undo();
|
||||
this.update_layer_action.free();
|
||||
this.update_layer_action = null;
|
||||
}
|
||||
if (this.delete_layer_action) {
|
||||
await this.delete_layer_action.undo();
|
||||
this.delete_layer_action.free();
|
||||
this.delete_layer_action = null;
|
||||
}
|
||||
config.layer = this.previous_selected_layer;
|
||||
this.previous_selected_layer = null;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
if (this.delete_layer_action) {
|
||||
this.delete_layer_action.free();
|
||||
this.delete_layer_action = null;
|
||||
}
|
||||
if (this.update_layer_action) {
|
||||
this.update_layer_action.free();
|
||||
this.update_layer_action = null;
|
||||
}
|
||||
this.previous_selected_layer = null;
|
||||
}
|
||||
}
|
||||
29
src/js/actions/prepare-canvas.js
Normal file
@ -0,0 +1,29 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Prepare_canvas_action extends Base_action {
|
||||
/**
|
||||
* Resizes/renders the canvas at the specified step. Usually used on both sides of a config update action.
|
||||
*
|
||||
* @param {boolean} call_when
|
||||
*/
|
||||
constructor(call_when = 'undo') {
|
||||
super('prepare_canvas', 'Prepare Canvas');
|
||||
this.call_when = call_when;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
if (this.call_when === 'do') {
|
||||
app.GUI.prepare_canvas();
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.call_when === 'undo') {
|
||||
app.GUI.prepare_canvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/js/actions/refresh-action-attributes.js
Normal file
@ -0,0 +1,29 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Refresh_action_attributes_action extends Base_action {
|
||||
/**
|
||||
* Resizes/renders the canvas at the specified step. Usually used on both sides of a config update action.
|
||||
*
|
||||
* @param {boolean} call_when
|
||||
*/
|
||||
constructor(call_when = 'undo') {
|
||||
super('refresh_action_attributes', 'Refresh Action Attributes');
|
||||
this.call_when = call_when;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
if (this.call_when === 'do') {
|
||||
app.GUI.GUI_tools.show_action_attributes();
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.call_when === 'undo') {
|
||||
app.GUI.GUI_tools.show_action_attributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/js/actions/refresh-layers-gui.js
Normal file
@ -0,0 +1,29 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Refresh_layers_gui_action extends Base_action {
|
||||
/**
|
||||
* Resizes/renders the canvas at the specified step. Usually used on both sides of a config update action.
|
||||
*
|
||||
* @param {boolean} call_when
|
||||
*/
|
||||
constructor(call_when = 'undo') {
|
||||
super('refresh_gui', 'Refresh GUI');
|
||||
this.call_when = call_when;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
if (this.call_when === 'do') {
|
||||
app.Layers.refresh_gui();
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.call_when === 'undo') {
|
||||
app.Layers.refresh_gui();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/js/actions/reorder-layer.js
Normal file
@ -0,0 +1,64 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Reorder_layer_action extends Base_action {
|
||||
/**
|
||||
* Reorder layer up or down in the layer stack
|
||||
*
|
||||
* @param {int} layer_id
|
||||
* @param {int} direction
|
||||
*/
|
||||
constructor(layer_id, direction) {
|
||||
super('reorder_layer', 'Reorder Layer');
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.direction = direction;
|
||||
this.reference_layer = null;
|
||||
this.reference_target = null;
|
||||
this.old_layer_order = null;
|
||||
this.old_target_order = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
if (this.direction < 0) {
|
||||
this.reference_target = app.Layers.find_previous(this.layer_id);
|
||||
}
|
||||
else {
|
||||
this.reference_target = app.Layers.find_next(this.layer_id);
|
||||
}
|
||||
if (!this.reference_target) {
|
||||
throw new Error('Aborted - layer has nowhere to move');
|
||||
}
|
||||
this.old_layer_order = this.reference_layer.order;
|
||||
this.old_target_order = this.reference_target.order;
|
||||
this.reference_layer.order = this.old_target_order;
|
||||
this.reference_target.order = this.old_layer_order;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.reference_layer) {
|
||||
this.reference_layer.order = this.old_layer_order;
|
||||
this.reference_layer = null;
|
||||
}
|
||||
if (this.reference_target) {
|
||||
this.reference_target.order = this.old_target_order;
|
||||
this.reference_target = null;
|
||||
}
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
this.reference_layer = null;
|
||||
this.reference_target = null;
|
||||
}
|
||||
}
|
||||
66
src/js/actions/reset-layers.js
Normal file
@ -0,0 +1,66 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Reset_layers_action extends Base_action {
|
||||
/*
|
||||
* removes all layers
|
||||
*/
|
||||
constructor(auto_insert) {
|
||||
super('reset_layers', 'Reset Layers');
|
||||
this.auto_insert = auto_insert;
|
||||
this.previous_auto_increment = null;
|
||||
this.delete_actions = null;
|
||||
this.insert_action = null;
|
||||
}
|
||||
async do() {
|
||||
super.do();
|
||||
const auto_insert = this.auto_insert;
|
||||
this.previous_auto_increment = app.Layers.auto_increment;
|
||||
|
||||
this.delete_actions = [];
|
||||
for (let i = config.layers.length - 1; i >= 0; i--) {
|
||||
const delete_action = new app.Actions.Delete_layer_action(config.layers[i].id, true);
|
||||
await delete_action.do();
|
||||
this.delete_actions.push(delete_action);
|
||||
}
|
||||
app.Layers.auto_increment = 1;
|
||||
|
||||
if (auto_insert != undefined && auto_insert === true) {
|
||||
const settings = {};
|
||||
this.insert_action = new app.Actions.Insert_layer_action(settings);
|
||||
await this.insert_action.do();
|
||||
}
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.insert_action) {
|
||||
await this.insert_action.undo();
|
||||
this.insert_action.free();
|
||||
this.insert_action = null;
|
||||
}
|
||||
for (let i = this.delete_actions.length - 1; i >= 0; i--) {
|
||||
await this.delete_actions[i].undo();
|
||||
this.delete_actions[i].free();
|
||||
}
|
||||
app.Layers.auto_increment = this.previous_auto_increment;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
free() {
|
||||
if (this.insert_action) {
|
||||
this.insert_action.free();
|
||||
this.insert_action = null;
|
||||
}
|
||||
if (this.delete_actions) {
|
||||
for (let action of this.delete_actions) {
|
||||
action.free();
|
||||
}
|
||||
this.delete_actions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/js/actions/reset-selection.js
Normal file
@ -0,0 +1,57 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Reset_selection_action extends Base_action {
|
||||
/**
|
||||
* Sets the selection to empty
|
||||
*
|
||||
* @prop {object} [mirror_selection_settings] - Optional object to also set to an empty selection object
|
||||
*/
|
||||
constructor(mirror_selection_settings) {
|
||||
super('reset_selection', 'Reset Selection');
|
||||
this.mirror_selection_settings = mirror_selection_settings;
|
||||
this.settings_reference = null;
|
||||
this.old_settings_data = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.settings_reference = app.Layers.Base_selection.find_settings();
|
||||
this.old_settings_data = JSON.parse(JSON.stringify(this.settings_reference.data));
|
||||
this.settings_reference.data = {
|
||||
x: null,
|
||||
y: null,
|
||||
width: null,
|
||||
height: null
|
||||
}
|
||||
if (this.mirror_selection_settings) {
|
||||
this.mirror_selection_settings.x = null;
|
||||
this.mirror_selection_settings.y = null;
|
||||
this.mirror_selection_settings.width = null;
|
||||
this.mirror_selection_settings.height = null;
|
||||
}
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.old_settings_data) {
|
||||
for (let prop of ['x', 'y', 'width', 'height']) {
|
||||
this.settings_reference.data[prop] = this.old_settings_data[prop];
|
||||
if (this.mirror_selection_settings) {
|
||||
this.mirror_selection_settings[prop] = this.old_settings_data[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.settings_reference = null;
|
||||
this.old_settings_data = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.settings_reference = null;
|
||||
this.old_settings_data = null;
|
||||
this.mirror_selection_settings = null;
|
||||
}
|
||||
}
|
||||
57
src/js/actions/select-layer.js
Normal file
@ -0,0 +1,57 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Select_layer_action extends Base_action {
|
||||
/**
|
||||
* marks layer as selected, active
|
||||
*
|
||||
* @param {int} layer_id
|
||||
*/
|
||||
constructor(layer_id, ignore_same_selection = false) {
|
||||
super('select_layer', 'Select Layer');
|
||||
this.reset_selection_action = null;
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.ignore_same_selection = ignore_same_selection;
|
||||
this.old_layer = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
|
||||
let old_layer = config.layer;
|
||||
let new_layer = app.Layers.get_layer(this.layer_id);
|
||||
|
||||
if (old_layer !== new_layer) {
|
||||
this.old_layer = old_layer;
|
||||
config.layer = new_layer;
|
||||
} else if (!this.ignore_same_selection) {
|
||||
throw new Error('Aborted - Layer already selected');
|
||||
}
|
||||
|
||||
this.reset_selection_action = new app.Actions.Reset_selection_action();
|
||||
await this.reset_selection_action.do();
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
|
||||
if (this.reset_selection_action) {
|
||||
await this.reset_selection_action.undo();
|
||||
this.reset_selection_action = null;
|
||||
}
|
||||
|
||||
config.layer = this.old_layer;
|
||||
this.old_layer = null;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
free() {
|
||||
this.old_layer = null;
|
||||
}
|
||||
}
|
||||
33
src/js/actions/select-next-layer.js
Normal file
@ -0,0 +1,33 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Select_next_layer_action extends Base_action {
|
||||
constructor(reference_layer_id) {
|
||||
super('select_next_layer', 'Select Next Layer');
|
||||
this.reference_layer_id = reference_layer_id;
|
||||
this.old_config_layer = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const next_layer = app.Layers.find_next(this.reference_layer_id);
|
||||
if (!next_layer) {
|
||||
throw new Error('Aborted - Next layer to select not found');
|
||||
}
|
||||
this.old_config_layer = config.layer;
|
||||
config.layer = next_layer;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
config.layer = this.old_config_layer;
|
||||
this.old_config_layer = null;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
}
|
||||
33
src/js/actions/select-previous-layer.js
Normal file
@ -0,0 +1,33 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Select_previous_layer_action extends Base_action {
|
||||
constructor(reference_layer_id) {
|
||||
super('select_previous_layer', 'Select Previous Layer');
|
||||
this.reference_layer_id = reference_layer_id;
|
||||
this.old_config_layer = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const previous_layer = app.Layers.find_previous(this.reference_layer_id);
|
||||
if (!previous_layer) {
|
||||
throw new Error('Aborted - Previous layer to select not found');
|
||||
}
|
||||
this.old_config_layer = config.layer;
|
||||
config.layer = previous_layer;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
config.layer = this.old_config_layer;
|
||||
this.old_config_layer = null;
|
||||
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
}
|
||||
35
src/js/actions/set-object-property.js
Normal file
@ -0,0 +1,35 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Set_object_property_action extends Base_action {
|
||||
/**
|
||||
* Sets a generic object property. I recommend against using this as it's generally a hack for edge cases.
|
||||
*
|
||||
* @param {string} layer_id
|
||||
* @param {object} settings
|
||||
*/
|
||||
constructor(object, property_name, value) {
|
||||
super('set_object_property', 'Set Object Property');
|
||||
this.object = object;
|
||||
this.property_name = property_name;
|
||||
this.value = value;
|
||||
this.old_value = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.old_value = this.object[this.property_name];
|
||||
this.object[this.property_name] = this.value;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
this.object[this.property_name] = this.old_value;
|
||||
this.old_value = null;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.object = null;
|
||||
}
|
||||
}
|
||||
57
src/js/actions/set-selection.js
Normal file
@ -0,0 +1,57 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Set_selection_action extends Base_action {
|
||||
/**
|
||||
* Sets the selection to the specified position and dimensions
|
||||
*/
|
||||
constructor(x, y, width, height, old_settings_override) {
|
||||
super('set_selection', 'Set Selection');
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.settings_reference = null;
|
||||
this.old_settings_data = null;
|
||||
this.old_settings_override = old_settings_override ? JSON.parse(JSON.stringify(old_settings_override)) || null : null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.settings_reference = app.Layers.Base_selection.find_settings();
|
||||
this.old_settings_data = JSON.parse(JSON.stringify(this.settings_reference.data));
|
||||
if (this.x != null)
|
||||
this.settings_reference.data.x = this.x;
|
||||
if (this.y != null)
|
||||
this.settings_reference.data.y = this.y;
|
||||
if (this.width != null)
|
||||
this.settings_reference.data.width = this.width;
|
||||
if (this.height != null)
|
||||
this.settings_reference.data.height = this.height;
|
||||
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo()
|
||||
if (this.old_settings_override) {
|
||||
for (let prop in this.old_settings_override) {
|
||||
this.settings_reference.data[prop] = this.old_settings_override[prop];
|
||||
}
|
||||
} else {
|
||||
for (let prop in this.old_settings_data) {
|
||||
this.settings_reference.data[prop] = this.old_settings_data[prop];
|
||||
}
|
||||
}
|
||||
this.settings_reference = null;
|
||||
this.old_settings_data = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.settings_reference = null;
|
||||
this.old_settings_override = null;
|
||||
this.old_settings_data = null;
|
||||
}
|
||||
}
|
||||
59
src/js/actions/stop-animation.js
Normal file
@ -0,0 +1,59 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Stop_animation_action extends Base_action {
|
||||
/**
|
||||
* Stops the currently playing animation, both do and undo states will stop animation
|
||||
*/
|
||||
constructor(reset_layer_visibility) {
|
||||
super('stop_animation', 'Stop Animation');
|
||||
this.reset_layer_visibility = !!reset_layer_visibility;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const animation_tool = app.GUI.GUI_tools.tools_modules.animation.object;
|
||||
var params = animation_tool.getParams();
|
||||
if (animation_tool.intervalID == null)
|
||||
return;
|
||||
|
||||
clearInterval(animation_tool.intervalID);
|
||||
params.play = false;
|
||||
animation_tool.index = 0;
|
||||
animation_tool.GUI_tools.show_action_attributes();
|
||||
|
||||
// make all visible
|
||||
if (this.reset_layer_visibility) {
|
||||
for (let i in config.layers) {
|
||||
config.layers[i].visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
animation_tool.Base_gui.GUI_layers.render_layers();
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
const animation_tool = app.GUI.GUI_tools.tools_modules.animation.object;
|
||||
var params = animation_tool.getParams();
|
||||
if (animation_tool.intervalID == null)
|
||||
return;
|
||||
|
||||
clearInterval(animation_tool.intervalID);
|
||||
params.play = false;
|
||||
animation_tool.index = 0;
|
||||
animation_tool.GUI_tools.show_action_attributes();
|
||||
|
||||
// make all visible
|
||||
if (this.reset_layer_visibility) {
|
||||
for (let i in config.layers) {
|
||||
config.layers[i].visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
animation_tool.Base_gui.GUI_layers.render_layers();
|
||||
config.need_render = true;
|
||||
}
|
||||
}
|
||||
222
src/js/actions/store/image-store.js
Normal file
@ -0,0 +1,222 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
// Get a unique id to identify this tab's history in the database
|
||||
let tabUuid;
|
||||
try {
|
||||
tabUuid = sessionStorage.getItem('history_tab_uuid');
|
||||
} catch (error) {}
|
||||
if (!tabUuid) {
|
||||
tabUuid = uuidv4();
|
||||
try {
|
||||
sessionStorage.setItem('history_tab_uuid', tabUuid);
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
let imageIdCounter = 0;
|
||||
let database = null;
|
||||
let databaseInitPromise = null;
|
||||
const tabPingInterval = 60000;
|
||||
const assumeTabIsClosedTimeout = 300000; // Inactive tabs setInterval is slowed down in most browsers, this should be significantly higher than tabPingInterval
|
||||
|
||||
export default {
|
||||
/**
|
||||
* Initializes the database
|
||||
*/
|
||||
async init() {
|
||||
if (!databaseInitPromise) {
|
||||
databaseInitPromise = new Promise(async (resolveInit) => {
|
||||
try {
|
||||
if (window.indexedDB) {
|
||||
// Delete database from a previous page load, if no other tabs have notified that they're open in a while
|
||||
let shouldDeleteDatabase = true;
|
||||
try {
|
||||
let lastDatabaseTabPing = localStorage.getItem('history_usage_ping');
|
||||
shouldDeleteDatabase = (!lastDatabaseTabPing || parseInt(lastDatabaseTabPing, 10) < new Date().getTime() - assumeTabIsClosedTimeout);
|
||||
} catch (error) {}
|
||||
if (shouldDeleteDatabase) {
|
||||
await new Promise((resolve, reject) => {
|
||||
let deleteRequest = window.indexedDB.deleteDatabase('undoHistoryImageStore');
|
||||
deleteRequest.onerror = () => {
|
||||
reject(deleteRequest.error);
|
||||
};
|
||||
deleteRequest.onsuccess = () => {
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
}
|
||||
// Initialize database
|
||||
await new Promise((resolve, reject) => {
|
||||
let openRequest = window.indexedDB.open('undoHistoryImageStore', 1);
|
||||
openRequest.onupgradeneeded = function(event) {
|
||||
database = openRequest.result;
|
||||
switch (event.oldVersion) {
|
||||
case 0:
|
||||
database.createObjectStore('images', { keyPath: 'id' });
|
||||
break;
|
||||
}
|
||||
};
|
||||
openRequest.onerror = () => {
|
||||
reject(openRequest.error);
|
||||
}
|
||||
openRequest.onsuccess = () => {
|
||||
resolve();
|
||||
database = openRequest.result;
|
||||
}
|
||||
});
|
||||
if (!database) {
|
||||
throw new Error('indexedDB not initialized');
|
||||
}
|
||||
// Delete history from previous session
|
||||
try {
|
||||
await this.delete_all();
|
||||
} catch (error) {}
|
||||
// Ping localStorage for as long as this browser tab is open
|
||||
localStorage.setItem('history_usage_ping', new Date().getTime() + '');
|
||||
setInterval(() => {
|
||||
localStorage.setItem('history_usage_ping', new Date().getTime() + '');
|
||||
}, tabPingInterval);
|
||||
}
|
||||
} catch (error) {
|
||||
database = {
|
||||
isMemory: true,
|
||||
images: {}
|
||||
};
|
||||
}
|
||||
resolveInit();
|
||||
});
|
||||
await databaseInitPromise;
|
||||
} else if (!database) {
|
||||
await databaseInitPromise;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the specified image to the database. Returns a promise that is resolved with an id that can be used to retrieve it again.
|
||||
*
|
||||
* @param {string | canvas | ImageData} imageData the image data to store
|
||||
* @returns {Promise<string>} resolves with retrieval id
|
||||
*/
|
||||
async add(imageData) {
|
||||
await this.init();
|
||||
let imageId = tabUuid + '-' + (imageIdCounter++);
|
||||
if (database.isMemory) {
|
||||
database.images[imageId] = imageData;
|
||||
} else {
|
||||
await new Promise((resolve, reject) => {
|
||||
const transaction = database.transaction('images', 'readwrite');
|
||||
const images = transaction.objectStore('images');
|
||||
const image = {
|
||||
id: imageId,
|
||||
tabUuid,
|
||||
data: imageData
|
||||
}
|
||||
const request = images.add(image);
|
||||
request.onsuccess = function() {
|
||||
resolve();
|
||||
};
|
||||
request.onerror = function() {
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
return imageId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the specified image from the database, by imageId retrieved from "add()" method.
|
||||
*
|
||||
* @param {string} imageId the id of the image to get
|
||||
* @returns {Promise<string | canvas | ImageData>} resolves with the image
|
||||
*/
|
||||
async get(imageId) {
|
||||
await this.init();
|
||||
if (database.isMemory) {
|
||||
return database.images[imageId];
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = database.transaction('images', 'readonly');
|
||||
const images = transaction.objectStore('images');
|
||||
const request = images.get(imageId);
|
||||
request.onsuccess = function() {
|
||||
resolve(request.result && request.result.data);
|
||||
};
|
||||
request.onerror = function() {
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes the specified image from the database, by imageId retrieved from "add()" method.
|
||||
*
|
||||
* @param {string} imageId the id of the image to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(imageId) {
|
||||
await this.init();
|
||||
if (database.isMemory) {
|
||||
delete database.images[imageId];
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = database.transaction('images', 'readwrite');
|
||||
const images = transaction.objectStore('images');
|
||||
const request = images.delete(imageId);
|
||||
request.onsuccess = function() {
|
||||
resolve();
|
||||
};
|
||||
request.onerror = function() {
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes all images associated with the current tab.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete_all() {
|
||||
await this.init();
|
||||
if (database.isMemory) {
|
||||
database.images = {};
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = database.transaction('images', 'readwrite');
|
||||
const images = transaction.objectStore('images');
|
||||
const getAllImagesRequest = images.getAll();
|
||||
getAllImagesRequest.onsuccess = async function () {
|
||||
const allImages = getAllImagesRequest.result;
|
||||
let errorOccurred = false;
|
||||
for (let image of allImages) {
|
||||
if (image.tabUuid === tabUuid) {
|
||||
try {
|
||||
await new Promise((deleteResolve, deleteReject) => {
|
||||
const request = images.delete(image.id);
|
||||
request.onsuccess = function() {
|
||||
deleteResolve();
|
||||
};
|
||||
request.onerror = function() {
|
||||
deleteReject(request.error);
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
errorOccurred = true;
|
||||
// Should eventually be deleted when database is deleted due to timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errorOccurred) {
|
||||
// Use a different uuid to prevent conflicts
|
||||
tabUuid = uuidv4();
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
getAllImagesRequest.onerror = function () {
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
37
src/js/actions/toggle-layer-visibility.js
Normal file
@ -0,0 +1,37 @@
|
||||
import app from '../app.js';
|
||||
import config from '../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Toggle_layer_visibility_action extends Base_action {
|
||||
/**
|
||||
* toggle layer visibility
|
||||
*
|
||||
* @param {int} layer_id
|
||||
*/
|
||||
constructor(layer_id) {
|
||||
super('toggle_layer_visibility', 'Toggle Layer Visibility');
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.old_visible = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
const layer = app.Layers.get_layer(this.layer_id);
|
||||
this.old_visible = layer.visible;
|
||||
if (layer.visible == false)
|
||||
layer.visible = true;
|
||||
else
|
||||
layer.visible = false;
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
const layer = app.Layers.get_layer(this.layer_id);
|
||||
layer.visible = this.old_visible;
|
||||
this.old_visible = null;
|
||||
app.Layers.render();
|
||||
app.GUI.GUI_layers.render_layers();
|
||||
}
|
||||
}
|
||||
37
src/js/actions/update-config.js
Normal file
@ -0,0 +1,37 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Update_config_action extends Base_action {
|
||||
/**
|
||||
* Updates the app config with the provided settings
|
||||
*
|
||||
* @param {object} settings
|
||||
*/
|
||||
constructor(settings) {
|
||||
super('update_config', 'Update Config');
|
||||
this.settings = settings;
|
||||
this.old_settings = {};
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
for (let i in this.settings) {
|
||||
this.old_settings[i] = config[i];
|
||||
config[i] = this.settings[i];
|
||||
}
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
for (let i in this.old_settings) {
|
||||
config[i] = this.old_settings[i];
|
||||
}
|
||||
this.old_settings = {};
|
||||
}
|
||||
|
||||
free() {
|
||||
this.settings = null;
|
||||
this.old_settings = null;
|
||||
}
|
||||
}
|
||||
149
src/js/actions/update-layer-image.js
Normal file
@ -0,0 +1,149 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import Helper_class from './../libs/helpers.js';
|
||||
import alertify from './../../../node_modules/alertifyjs/build/alertify.min.js';
|
||||
import image_store from './store/image-store.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
const Helper = new Helper_class();
|
||||
|
||||
export class Update_layer_image_action extends Base_action {
|
||||
/**
|
||||
* updates layer image data
|
||||
*
|
||||
* @param {canvas} canvas
|
||||
* @param {int} layer_id (optional)
|
||||
*/
|
||||
constructor(canvas, layer_id) {
|
||||
super('update_layer_image', 'Update Layer Image');
|
||||
this.canvas = canvas;
|
||||
if (layer_id == null)
|
||||
layer_id = config.layer.id;
|
||||
this.layer_id = parseInt(layer_id);
|
||||
this.reference_layer = null;
|
||||
this.old_image_id = null;
|
||||
this.new_image_id = null;
|
||||
this.old_link_database_id = null;
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
if (this.reference_layer.type != 'image'){
|
||||
alertify.error('Error: layer must be image.');
|
||||
throw new Error('Aborted - layer is not an image');
|
||||
}
|
||||
|
||||
// Get data url representation of image
|
||||
let canvas_data_url;
|
||||
if (this.new_image_id) {
|
||||
try {
|
||||
canvas_data_url = await image_store.get(this.new_image_id);
|
||||
} catch (error) {
|
||||
throw new Error('Aborted - problem retrieving cached image from database');
|
||||
}
|
||||
} else if (this.canvas) {
|
||||
if (Helper.is_edge_or_ie() == false && typeof(FileReader) !== 'undefined') {
|
||||
// Update image using blob and FileReader (async)
|
||||
await new Promise((resolve) => {
|
||||
this.canvas.toBlob((blob) => {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
canvas_data_url = reader.result;
|
||||
resolve();
|
||||
}
|
||||
reader.readAsDataURL(blob);
|
||||
}, 'image/png');
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Slow way for IE, Edge
|
||||
canvas_data_url = this.canvas.toDataURL();
|
||||
}
|
||||
}
|
||||
|
||||
// Store data url in database
|
||||
try {
|
||||
if (!this.old_image_id) {
|
||||
if (this.reference_layer._link_database_id) {
|
||||
this.old_image_id = this.reference_layer._link_database_id;
|
||||
} else {
|
||||
this.old_image_id = await image_store.add(this.reference_layer.link.src);
|
||||
}
|
||||
}
|
||||
if (!this.new_image_id) {
|
||||
this.new_image_id = await image_store.add(canvas_data_url);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
requestAnimationFrame(() => {
|
||||
app.State.free(0, this.database_estimate || 1)
|
||||
});
|
||||
}
|
||||
|
||||
// Estimate storage size
|
||||
try {
|
||||
this.database_estimate = new Blob([await image_store.get(this.old_image_id)]).size;
|
||||
} catch (e) {}
|
||||
|
||||
// Assign layer properties
|
||||
this.reference_layer.link.src = canvas_data_url;
|
||||
this.old_link_database_id = this.reference_layer._link_database_id;
|
||||
this.reference_layer._link_database_id = this.new_image_id;
|
||||
|
||||
this.canvas = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
|
||||
// Estimate storage size
|
||||
try {
|
||||
this.database_estimate = new Blob([this.reference_layer.link.src]).size;
|
||||
} catch (e) {}
|
||||
|
||||
// Restore old image
|
||||
if (this.old_image_id != null) {
|
||||
try {
|
||||
this.reference_layer.link.src = await image_store.get(this.old_image_id);
|
||||
} catch (error) {
|
||||
throw new Error('Failed to retrieve image from store');
|
||||
}
|
||||
}
|
||||
this.reference_layer._link_database_id = this.old_link_database_id;
|
||||
this.reference_layer = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async free() {
|
||||
let has_error = false;
|
||||
if (this.new_image_id != null) {
|
||||
try {
|
||||
await image_store.delete(this.new_image_id);
|
||||
} catch (error) {
|
||||
has_error = true;
|
||||
}
|
||||
this.new_image_id = null;
|
||||
}
|
||||
if (this.is_done || !this.old_link_database_id) {
|
||||
if (this.old_image_id != null) {
|
||||
try {
|
||||
await image_store.delete(this.old_image_id);
|
||||
} catch (error) {
|
||||
has_error = true;
|
||||
}
|
||||
this.old_image_id = null;
|
||||
}
|
||||
}
|
||||
this.canvas = null;
|
||||
this.old_link_database_id = null;
|
||||
this.reference_layer = null;
|
||||
if (has_error) {
|
||||
alertify.error('A problem occurred while removing undo history. It\'s suggested you save your work and refresh the page in order to free up memory.');
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/js/actions/update-layer.js
Normal file
@ -0,0 +1,67 @@
|
||||
import app from './../app.js';
|
||||
import config from './../config.js';
|
||||
import { Base_action } from './base.js';
|
||||
|
||||
export class Update_layer_action extends Base_action {
|
||||
/**
|
||||
* Updates an existing layer with the provided settings
|
||||
* WARNING: If passing objects or arrays into settings, make sure these are new or cloned objects, and not a modified existing object!
|
||||
*
|
||||
* @param {string} layer_id
|
||||
* @param {object} settings
|
||||
*/
|
||||
constructor(layer_id, settings) {
|
||||
super('update_layer', 'Update Layer');
|
||||
this.layer_id = layer_id;
|
||||
this.settings = settings;
|
||||
this.reference_layer = null;
|
||||
this.old_settings = {};
|
||||
}
|
||||
|
||||
async do() {
|
||||
super.do();
|
||||
this.reference_layer = app.Layers.get_layer(this.layer_id);
|
||||
if (!this.reference_layer) {
|
||||
throw new Error('Aborted - layer with specified id doesn\'t exist');
|
||||
}
|
||||
for (let i in this.settings) {
|
||||
if (i == 'id')
|
||||
continue;
|
||||
if (i == 'order')
|
||||
continue;
|
||||
this.old_settings[i] = this.reference_layer[i];
|
||||
this.reference_layer[i] = this.settings[i];
|
||||
}
|
||||
if (this.reference_layer.type === 'text') {
|
||||
this.reference_layer._needs_update_data = true;
|
||||
}
|
||||
if (this.settings.params || this.settings.width || this.settings.height) {
|
||||
config.need_render_changed_params = true;
|
||||
}
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
async undo() {
|
||||
super.undo();
|
||||
if (this.reference_layer) {
|
||||
for (let i in this.old_settings) {
|
||||
this.reference_layer[i] = this.old_settings[i];
|
||||
}
|
||||
if (this.reference_layer.type === 'text') {
|
||||
this.reference_layer._needs_update_data = true;
|
||||
}
|
||||
if (this.old_settings.params || this.old_settings.width || this.old_settings.height) {
|
||||
config.need_render_changed_params = true;
|
||||
}
|
||||
this.old_settings = {};
|
||||
}
|
||||
this.reference_layer = null;
|
||||
config.need_render = true;
|
||||
}
|
||||
|
||||
free() {
|
||||
this.settings = null;
|
||||
this.old_settings = null;
|
||||
this.reference_layer = null;
|
||||
}
|
||||
}
|
||||
11
src/js/app.js
Normal file
@ -0,0 +1,11 @@
|
||||
// Store singletons for easy access
|
||||
export default {
|
||||
GUI: null,
|
||||
Tools: null,
|
||||
Layers: null,
|
||||
Config: null,
|
||||
State: null,
|
||||
FileOpen: null,
|
||||
FileSave: null,
|
||||
Actions: null
|
||||
};
|
||||