Compare commits

...

2165 Commits

Author SHA1 Message Date
Excalidraw Bot
c507d1726a New translations en.json (Portuguese) 2025-02-04 11:04:24 +01:00
Excalidraw Bot
d6ef71c15c New translations en.json (German) 2025-01-22 20:35:23 +01:00
Excalidraw Bot
4b9978cd57 New translations en.json (Slovak) 2025-01-21 03:20:22 +01:00
Excalidraw Bot
79cac89d45 New translations en.json (Hindi) 2025-01-16 07:15:41 +01:00
Excalidraw Bot
2651ce2e9b New translations en.json (Marathi) 2025-01-16 07:15:40 +01:00
Excalidraw Bot
6c3c6f26d9 New translations en.json (Chinese Simplified) 2025-01-16 01:06:46 +01:00
Excalidraw Bot
38da08662c New translations en.json (Spanish) 2025-01-14 14:59:30 +01:00
Excalidraw Bot
571053aec9 New translations en.json (Romanian) 2025-01-14 11:01:30 +01:00
Excalidraw Bot
88b3d9b6a5 New translations en.json (Russian) 2025-01-13 19:17:34 +01:00
Excalidraw Bot
f2b9da3255 New translations en.json (German) 2025-01-13 18:13:41 +01:00
Excalidraw Bot
ba4a9f1e82 New translations en.json (Karakalpak) 2025-01-13 17:08:29 +01:00
Excalidraw Bot
90ee80a3fa New translations en.json (Kabyle) 2025-01-13 17:08:28 +01:00
Excalidraw Bot
01c6cbefbc New translations en.json (Bengali, India) 2025-01-13 17:08:27 +01:00
Excalidraw Bot
8aee0f5f24 New translations en.json (German, Switzerland) 2025-01-13 17:08:26 +01:00
Excalidraw Bot
d865bfb985 New translations en.json (Occitan) 2025-01-13 17:08:25 +01:00
Excalidraw Bot
4ac707927a New translations en.json (Norwegian Bokmal) 2025-01-13 17:08:24 +01:00
Excalidraw Bot
e102ee38cd New translations en.json (Uzbek) 2025-01-13 17:08:23 +01:00
Excalidraw Bot
4df31a063a New translations en.json (Sinhala) 2025-01-13 17:08:21 +01:00
Excalidraw Bot
f8e0e7cda9 New translations en.json (Chinese Traditional, Hong Kong) 2025-01-13 17:08:20 +01:00
Excalidraw Bot
bfd79929b7 New translations en.json (Burmese) 2025-01-13 17:08:19 +01:00
Excalidraw Bot
182df6516a New translations en.json (Hindi) 2025-01-13 17:08:17 +01:00
Excalidraw Bot
08840c89ca New translations en.json (Azerbaijani) 2025-01-13 17:08:16 +01:00
Excalidraw Bot
30cf52e15c New translations en.json (Latvian) 2025-01-13 17:08:15 +01:00
Excalidraw Bot
09f2f38ce7 New translations en.json (Kazakh) 2025-01-13 17:08:14 +01:00
Excalidraw Bot
df54053d44 New translations en.json (Norwegian Nynorsk) 2025-01-13 17:08:13 +01:00
Excalidraw Bot
1850a09ffd New translations en.json (Thai) 2025-01-13 17:08:11 +01:00
Excalidraw Bot
16e2694301 New translations en.json (Marathi) 2025-01-13 17:08:10 +01:00
Excalidraw Bot
48fdd416e4 New translations en.json (Bengali) 2025-01-13 17:08:09 +01:00
Excalidraw Bot
0e71b552a0 New translations en.json (Tamil) 2025-01-13 17:08:08 +01:00
Excalidraw Bot
201df105a0 New translations en.json (Khmer) 2025-01-13 17:08:06 +01:00
Excalidraw Bot
8b0297e024 New translations en.json (Persian) 2025-01-13 17:08:05 +01:00
Excalidraw Bot
88f2d3d848 New translations en.json (Indonesian) 2025-01-13 17:08:04 +01:00
Excalidraw Bot
2262458d08 New translations en.json (Portuguese, Brazilian) 2025-01-13 17:08:02 +01:00
Excalidraw Bot
367dbb6a20 New translations en.json (Galician) 2025-01-13 17:08:01 +01:00
Excalidraw Bot
15bb6af068 New translations en.json (Vietnamese) 2025-01-13 17:08:00 +01:00
Excalidraw Bot
0da5f82b4b New translations en.json (Chinese Simplified) 2025-01-13 17:07:58 +01:00
Excalidraw Bot
b6fadd90c6 New translations en.json (Ukrainian) 2025-01-13 17:07:57 +01:00
Excalidraw Bot
f4dd5ced14 New translations en.json (Turkish) 2025-01-13 17:07:56 +01:00
Excalidraw Bot
67b4a6083e New translations en.json (Swedish) 2025-01-13 17:07:54 +01:00
Excalidraw Bot
d011d8ffbe New translations en.json (Slovenian) 2025-01-13 17:07:53 +01:00
Excalidraw Bot
9341ae94fe New translations en.json (Russian) 2025-01-13 17:07:52 +01:00
Excalidraw Bot
5d9d93e400 New translations en.json (Portuguese) 2025-01-13 17:07:51 +01:00
Excalidraw Bot
8660a48958 New translations en.json (Polish) 2025-01-13 17:07:49 +01:00
Excalidraw Bot
361cb1b94c New translations en.json (Punjabi) 2025-01-13 17:07:48 +01:00
Excalidraw Bot
4282f3c2dc New translations en.json (Dutch) 2025-01-13 17:07:47 +01:00
Excalidraw Bot
37ee37caaa New translations en.json (Lithuanian) 2025-01-13 17:07:46 +01:00
Excalidraw Bot
9ef56c2b20 New translations en.json (Kurdish) 2025-01-13 17:07:44 +01:00
Excalidraw Bot
7f235f5830 New translations en.json (Japanese) 2025-01-13 17:07:43 +01:00
Excalidraw Bot
cbe30a553f New translations en.json (Italian) 2025-01-13 17:07:42 +01:00
Excalidraw Bot
28eef4fc08 New translations en.json (Finnish) 2025-01-13 17:07:41 +01:00
Excalidraw Bot
10bf4dae6b New translations en.json (Basque) 2025-01-13 17:07:39 +01:00
Excalidraw Bot
ccb2b9e5e2 New translations en.json (Greek) 2025-01-13 17:07:38 +01:00
Excalidraw Bot
25c9334ebe New translations en.json (German) 2025-01-13 17:07:36 +01:00
Excalidraw Bot
057a5b555a New translations en.json (Danish) 2025-01-13 17:07:34 +01:00
Excalidraw Bot
7adb935619 New translations en.json (Czech) 2025-01-13 17:07:33 +01:00
Excalidraw Bot
6d6bb7a6d0 New translations en.json (Catalan) 2025-01-13 17:07:31 +01:00
Excalidraw Bot
7fa8edcdfe New translations en.json (Bulgarian) 2025-01-13 17:07:29 +01:00
Excalidraw Bot
63facdd1b3 New translations en.json (Arabic) 2025-01-13 17:07:28 +01:00
Excalidraw Bot
0ead775db7 New translations en.json (Spanish) 2025-01-13 17:07:27 +01:00
Excalidraw Bot
5af0f1c11e New translations en.json (French) 2025-01-13 17:07:25 +01:00
Excalidraw Bot
fd5c2b81d8 New translations en.json (Romanian) 2025-01-13 17:07:24 +01:00
Excalidraw Bot
052e456826 New translations en.json (Chinese Traditional) 2025-01-13 17:07:23 +01:00
Excalidraw Bot
0e71e2e49b New translations en.json (Korean) 2025-01-13 17:07:22 +01:00
Excalidraw Bot
0d50481428 New translations en.json (Hungarian) 2025-01-13 17:07:21 +01:00
Excalidraw Bot
c82882e7e4 New translations en.json (Hebrew) 2025-01-13 17:07:19 +01:00
Excalidraw Bot
62bd7cca34 New translations en.json (Slovak) 2025-01-13 17:07:18 +01:00
Excalidraw Bot
0e37679c89 New translations en.json (Slovak) 2025-01-13 02:34:56 +01:00
Excalidraw Bot
cfcac1d74d New translations en.json (Turkish) 2025-01-09 20:19:36 +01:00
Excalidraw Bot
f8935be5fd New translations en.json (Chinese Traditional) 2025-01-07 08:35:18 +01:00
Excalidraw Bot
2ad3c1e3a0 New translations en.json (Russian) 2025-01-06 20:51:27 +01:00
Excalidraw Bot
8c69e77458 New translations en.json (Spanish) 2025-01-06 17:36:56 +01:00
Excalidraw Bot
7c60960708 New translations en.json (Chinese Simplified) 2025-01-06 06:18:41 +01:00
Excalidraw Bot
c050f50920 New translations en.json (Slovenian) 2025-01-05 23:23:46 +01:00
Excalidraw Bot
fc0364e49b New translations en.json (German) 2025-01-05 23:23:44 +01:00
Excalidraw Bot
1c2bc960e3 New translations en.json (Romanian) 2025-01-05 23:23:43 +01:00
Excalidraw Bot
fa3e95e62d New translations en.json (Karakalpak) 2025-01-05 22:14:04 +01:00
Excalidraw Bot
91ff8ece0d New translations en.json (Kabyle) 2025-01-05 22:14:03 +01:00
Excalidraw Bot
08241465c4 New translations en.json (Bengali, India) 2025-01-05 22:14:02 +01:00
Excalidraw Bot
4a70e3c8c6 New translations en.json (German, Switzerland) 2025-01-05 22:14:01 +01:00
Excalidraw Bot
58ae2ef67f New translations en.json (Occitan) 2025-01-05 22:14:00 +01:00
Excalidraw Bot
d4474ce348 New translations en.json (Norwegian Bokmal) 2025-01-05 22:13:59 +01:00
Excalidraw Bot
a02df75456 New translations en.json (Uzbek) 2025-01-05 22:13:58 +01:00
Excalidraw Bot
e0d1d4ae53 New translations en.json (Sinhala) 2025-01-05 22:13:57 +01:00
Excalidraw Bot
91f906d122 New translations en.json (Chinese Traditional, Hong Kong) 2025-01-05 22:13:56 +01:00
Excalidraw Bot
8e76a3576a New translations en.json (Burmese) 2025-01-05 22:13:55 +01:00
Excalidraw Bot
575ba7c167 New translations en.json (Hindi) 2025-01-05 22:13:54 +01:00
Excalidraw Bot
f4ea623e65 New translations en.json (Azerbaijani) 2025-01-05 22:13:52 +01:00
Excalidraw Bot
a74946d8ba New translations en.json (Latvian) 2025-01-05 22:13:51 +01:00
Excalidraw Bot
5cf9ce5a19 New translations en.json (Kazakh) 2025-01-05 22:13:50 +01:00
Excalidraw Bot
06b26a347e New translations en.json (Norwegian Nynorsk) 2025-01-05 22:13:50 +01:00
Excalidraw Bot
4a071e90e8 New translations en.json (Thai) 2025-01-05 22:13:48 +01:00
Excalidraw Bot
11e7ea11df New translations en.json (Marathi) 2025-01-05 22:13:48 +01:00
Excalidraw Bot
01b0ac438c New translations en.json (Bengali) 2025-01-05 22:13:46 +01:00
Excalidraw Bot
3b6c1fdbaa New translations en.json (Tamil) 2025-01-05 22:13:45 +01:00
Excalidraw Bot
a6119a0910 New translations en.json (Khmer) 2025-01-05 22:13:44 +01:00
Excalidraw Bot
c42898a939 New translations en.json (Persian) 2025-01-05 22:13:43 +01:00
Excalidraw Bot
aaa239113f New translations en.json (Indonesian) 2025-01-05 22:13:42 +01:00
Excalidraw Bot
110d3d7c69 New translations en.json (Portuguese, Brazilian) 2025-01-05 22:13:41 +01:00
Excalidraw Bot
1e9fe91adf New translations en.json (Galician) 2025-01-05 22:13:40 +01:00
Excalidraw Bot
b8baa27839 New translations en.json (Vietnamese) 2025-01-05 22:13:39 +01:00
Excalidraw Bot
c1c2091a88 New translations en.json (Chinese Simplified) 2025-01-05 22:13:38 +01:00
Excalidraw Bot
8f7aa71a4c New translations en.json (Ukrainian) 2025-01-05 22:13:37 +01:00
Excalidraw Bot
d38ea58a27 New translations en.json (Turkish) 2025-01-05 22:13:36 +01:00
Excalidraw Bot
cb62a51426 New translations en.json (Swedish) 2025-01-05 22:13:35 +01:00
Excalidraw Bot
c300216307 New translations en.json (Slovenian) 2025-01-05 22:13:34 +01:00
Excalidraw Bot
a01bbedada New translations en.json (Russian) 2025-01-05 22:13:33 +01:00
Excalidraw Bot
0d9e1e8f92 New translations en.json (Portuguese) 2025-01-05 22:13:32 +01:00
Excalidraw Bot
93a95db1b2 New translations en.json (Polish) 2025-01-05 22:13:31 +01:00
Excalidraw Bot
b22d830b3b New translations en.json (Punjabi) 2025-01-05 22:13:30 +01:00
Excalidraw Bot
de09e6867c New translations en.json (Dutch) 2025-01-05 22:13:29 +01:00
Excalidraw Bot
6f37102175 New translations en.json (Lithuanian) 2025-01-05 22:13:28 +01:00
Excalidraw Bot
351aac987b New translations en.json (Kurdish) 2025-01-05 22:13:27 +01:00
Excalidraw Bot
9c534fe870 New translations en.json (Japanese) 2025-01-05 22:13:26 +01:00
Excalidraw Bot
fbe2745b2d New translations en.json (Italian) 2025-01-05 22:13:25 +01:00
Excalidraw Bot
cfa03593a6 New translations en.json (Finnish) 2025-01-05 22:13:24 +01:00
Excalidraw Bot
b13771496f New translations en.json (Basque) 2025-01-05 22:13:23 +01:00
Excalidraw Bot
a7cc1247d1 New translations en.json (Greek) 2025-01-05 22:13:22 +01:00
Excalidraw Bot
323008553e New translations en.json (German) 2025-01-05 22:13:21 +01:00
Excalidraw Bot
253017fe8e New translations en.json (Danish) 2025-01-05 22:13:20 +01:00
Excalidraw Bot
97ee0973dd New translations en.json (Czech) 2025-01-05 22:13:19 +01:00
Excalidraw Bot
a0f3c50ceb New translations en.json (Catalan) 2025-01-05 22:13:18 +01:00
Excalidraw Bot
0a9ae2505d New translations en.json (Bulgarian) 2025-01-05 22:13:17 +01:00
Excalidraw Bot
5bb7a37121 New translations en.json (Arabic) 2025-01-05 22:13:16 +01:00
Excalidraw Bot
532c4bb639 New translations en.json (Spanish) 2025-01-05 22:13:15 +01:00
Excalidraw Bot
218c9ef1c3 New translations en.json (French) 2025-01-05 22:13:14 +01:00
Excalidraw Bot
21016e21a5 New translations en.json (Romanian) 2025-01-05 22:13:13 +01:00
Excalidraw Bot
20ca0ccf12 New translations en.json (Chinese Traditional) 2025-01-05 22:13:12 +01:00
Excalidraw Bot
a96c2013b7 New translations en.json (Korean) 2025-01-05 22:13:10 +01:00
Excalidraw Bot
bf9733f7ef New translations en.json (Hungarian) 2025-01-05 22:13:09 +01:00
Excalidraw Bot
7566d96b35 New translations en.json (Hebrew) 2025-01-05 22:13:08 +01:00
Excalidraw Bot
4b8642d1d0 New translations en.json (Slovak) 2025-01-05 22:13:07 +01:00
Excalidraw Bot
3ca773f54d New translations en.json (Hungarian) 2024-12-31 16:17:49 +01:00
Excalidraw Bot
3dbdfdcffc New translations en.json (Hungarian) 2024-12-31 15:16:38 +01:00
Excalidraw Bot
4acea43b12 New translations en.json (Slovak) 2024-12-30 10:40:20 +01:00
Excalidraw Bot
aabc4b701e New translations en.json (Slovak) 2024-12-30 08:55:51 +01:00
Excalidraw Bot
1325c85a48 New translations en.json (Hebrew) 2024-12-28 00:16:03 +01:00
Excalidraw Bot
3f3134435e New translations en.json (Hebrew) 2024-12-27 22:51:12 +01:00
Excalidraw Bot
2d370b9360 New translations en.json (Chinese Traditional) 2024-12-23 10:29:20 +01:00
Excalidraw Bot
dab6df1a77 New translations en.json (Korean) 2024-12-23 07:42:22 +01:00
Excalidraw Bot
4390f6d75e New translations en.json (Romanian) 2024-12-18 11:57:51 +01:00
Excalidraw Bot
4d1730882b New translations en.json (Polish) 2024-12-18 10:37:52 +01:00
Excalidraw Bot
6bff123aea New translations en.json (Chinese Simplified) 2024-12-18 04:04:53 +01:00
Excalidraw Bot
e255caefc5 New translations en.json (German) 2024-12-17 21:04:56 +01:00
Excalidraw Bot
a62ebd7f71 New translations en.json (Hindi) 2024-12-17 18:15:21 +01:00
Excalidraw Bot
376d25ad8b New translations en.json (Marathi) 2024-12-17 18:15:19 +01:00
Excalidraw Bot
dfc89f9d6e New translations en.json (Russian) 2024-12-17 15:27:00 +01:00
Excalidraw Bot
62114e309f New translations en.json (Portuguese) 2024-12-17 15:26:58 +01:00
Excalidraw Bot
c6901cae98 New translations en.json (Karakalpak) 2024-12-17 14:11:42 +01:00
Excalidraw Bot
d4b760f7b3 New translations en.json (Kabyle) 2024-12-17 14:11:41 +01:00
Excalidraw Bot
5e21607153 New translations en.json (Bengali, India) 2024-12-17 14:11:40 +01:00
Excalidraw Bot
3e79c6caab New translations en.json (German, Switzerland) 2024-12-17 14:11:38 +01:00
Excalidraw Bot
fee26ea12c New translations en.json (Occitan) 2024-12-17 14:11:37 +01:00
Excalidraw Bot
b551e5336c New translations en.json (Norwegian Bokmal) 2024-12-17 14:11:36 +01:00
Excalidraw Bot
172ecace2f New translations en.json (Uzbek) 2024-12-17 14:11:35 +01:00
Excalidraw Bot
e146d42598 New translations en.json (Sinhala) 2024-12-17 14:11:33 +01:00
Excalidraw Bot
0546406d4b New translations en.json (Chinese Traditional, Hong Kong) 2024-12-17 14:11:32 +01:00
Excalidraw Bot
4a5ca8d3ea New translations en.json (Burmese) 2024-12-17 14:11:31 +01:00
Excalidraw Bot
267341b9b7 New translations en.json (Hindi) 2024-12-17 14:11:29 +01:00
Excalidraw Bot
c3a15bc297 New translations en.json (Azerbaijani) 2024-12-17 14:11:28 +01:00
Excalidraw Bot
4b1d99fbf4 New translations en.json (Latvian) 2024-12-17 14:11:27 +01:00
Excalidraw Bot
c4c1193094 New translations en.json (Kazakh) 2024-12-17 14:11:25 +01:00
Excalidraw Bot
03adc9b7bc New translations en.json (Norwegian Nynorsk) 2024-12-17 14:11:24 +01:00
Excalidraw Bot
fd491e45e9 New translations en.json (Thai) 2024-12-17 14:11:23 +01:00
Excalidraw Bot
a19c1d64e4 New translations en.json (Marathi) 2024-12-17 14:11:21 +01:00
Excalidraw Bot
836c8f2dba New translations en.json (Bengali) 2024-12-17 14:11:20 +01:00
Excalidraw Bot
01f2001a0d New translations en.json (Tamil) 2024-12-17 14:11:19 +01:00
Excalidraw Bot
8136b719bd New translations en.json (Khmer) 2024-12-17 14:11:18 +01:00
Excalidraw Bot
20870a78c2 New translations en.json (Persian) 2024-12-17 14:11:16 +01:00
Excalidraw Bot
e741a6f370 New translations en.json (Portuguese, Brazilian) 2024-12-17 14:11:15 +01:00
Excalidraw Bot
e76ef06074 New translations en.json (Galician) 2024-12-17 14:11:14 +01:00
Excalidraw Bot
0fd05e34c4 New translations en.json (Vietnamese) 2024-12-17 14:11:12 +01:00
Excalidraw Bot
b11c80361a New translations en.json (Chinese Traditional) 2024-12-17 14:11:11 +01:00
Excalidraw Bot
f19c0d14ed New translations en.json (Ukrainian) 2024-12-17 14:11:09 +01:00
Excalidraw Bot
b242a9df79 New translations en.json (Turkish) 2024-12-17 14:11:07 +01:00
Excalidraw Bot
9fed9613fa New translations en.json (Russian) 2024-12-17 14:11:06 +01:00
Excalidraw Bot
01fa484a5e New translations en.json (Polish) 2024-12-17 14:11:04 +01:00
Excalidraw Bot
9a7e1710a4 New translations en.json (Punjabi) 2024-12-17 14:11:03 +01:00
Excalidraw Bot
d1957e4056 New translations en.json (Dutch) 2024-12-17 14:11:02 +01:00
Excalidraw Bot
68c96c5c9f New translations en.json (Lithuanian) 2024-12-17 14:11:00 +01:00
Excalidraw Bot
617897be5b New translations en.json (Kurdish) 2024-12-17 14:10:59 +01:00
Excalidraw Bot
b116388c7e New translations en.json (Korean) 2024-12-17 14:10:57 +01:00
Excalidraw Bot
473d4da923 New translations en.json (Japanese) 2024-12-17 14:10:56 +01:00
Excalidraw Bot
4c15aa2cf2 New translations en.json (Indonesian) 2024-12-17 14:10:55 +01:00
Excalidraw Bot
73f1d98d06 New translations en.json (Portuguese) 2024-12-17 14:10:53 +01:00
Excalidraw Bot
4e75a68ad3 New translations en.json (Chinese Simplified) 2024-12-17 14:10:52 +01:00
Excalidraw Bot
c0cf71a6f5 New translations en.json (Swedish) 2024-12-17 14:10:50 +01:00
Excalidraw Bot
4b5b7e8f5a New translations en.json (Slovenian) 2024-12-17 14:10:49 +01:00
Excalidraw Bot
e0dff46a28 New translations en.json (Slovak) 2024-12-17 14:10:48 +01:00
Excalidraw Bot
505b6ace2b New translations en.json (Italian) 2024-12-17 14:10:47 +01:00
Excalidraw Bot
4845574506 New translations en.json (Hungarian) 2024-12-17 14:10:45 +01:00
Excalidraw Bot
a9f69d750b New translations en.json (Hebrew) 2024-12-17 14:10:44 +01:00
Excalidraw Bot
f883167acc New translations en.json (Finnish) 2024-12-17 14:10:43 +01:00
Excalidraw Bot
3d89b04ac4 New translations en.json (Basque) 2024-12-17 14:10:42 +01:00
Excalidraw Bot
3ffa6c93e4 New translations en.json (Greek) 2024-12-17 14:10:40 +01:00
Excalidraw Bot
6be95e9fbf New translations en.json (German) 2024-12-17 14:10:39 +01:00
Excalidraw Bot
be0d4241e4 New translations en.json (Danish) 2024-12-17 14:10:37 +01:00
Excalidraw Bot
dc0b951dfa New translations en.json (Catalan) 2024-12-17 14:10:36 +01:00
Excalidraw Bot
b92b0ec82b New translations en.json (Bulgarian) 2024-12-17 14:10:35 +01:00
Excalidraw Bot
774fd07ca8 New translations en.json (Arabic) 2024-12-17 14:10:34 +01:00
Excalidraw Bot
a18a1ace4d New translations en.json (Spanish) 2024-12-17 14:10:32 +01:00
Excalidraw Bot
728ac246d5 New translations en.json (French) 2024-12-17 14:10:31 +01:00
Excalidraw Bot
a1b5ff5372 New translations en.json (Romanian) 2024-12-17 14:10:30 +01:00
Excalidraw Bot
80b98ca5e4 New translations en.json (Czech) 2024-12-17 14:10:28 +01:00
Excalidraw Bot
4d22570b55 New translations en.json (Czech) 2024-12-17 12:44:37 +01:00
Excalidraw Bot
f1a2bb6677 New translations en.json (Indonesian) 2024-12-16 00:25:54 +01:00
Excalidraw Bot
b213e344fb New translations en.json (Indonesian) 2024-12-15 23:23:04 +01:00
Excalidraw Bot
ed61daeb16 New translations en.json (Portuguese) 2024-12-15 21:05:23 +01:00
Excalidraw Bot
4e752e95a3 New translations en.json (Chinese Simplified) 2024-12-12 03:59:20 +01:00
Excalidraw Bot
e459e07af5 New translations en.json (Swedish) 2024-12-09 08:39:44 +01:00
Excalidraw Bot
1aa82f1c80 New translations en.json (Slovak) 2024-12-07 17:51:15 +01:00
Excalidraw Bot
ae9dca08b5 New translations en.json (Slovak) 2024-12-07 16:55:39 +01:00
Excalidraw Bot
7af0ba734d New translations en.json (Slovenian) 2024-12-03 07:13:08 +01:00
Excalidraw Bot
d200ee2d0d New translations en.json (Italian) 2024-12-01 16:32:30 +01:00
Excalidraw Bot
597bde73d4 New translations en.json (Persian) 2024-11-30 14:11:06 +01:00
Excalidraw Bot
44642e29e4 New translations en.json (Persian) 2024-11-30 13:08:35 +01:00
Excalidraw Bot
d01091c094 New translations en.json (Persian) 2024-11-30 12:05:49 +01:00
Excalidraw Bot
9cbe0a89a7 New translations en.json (Chinese Traditional) 2024-11-28 15:43:42 +01:00
Excalidraw Bot
09c53b975e New translations en.json (Hindi) 2024-11-27 06:51:41 +01:00
Excalidraw Bot
356d13cae7 New translations en.json (Marathi) 2024-11-27 06:51:40 +01:00
Excalidraw Bot
37a3caf5a9 New translations en.json (Hindi) 2024-11-27 05:10:53 +01:00
Excalidraw Bot
baaad3a443 New translations en.json (Marathi) 2024-11-27 05:10:52 +01:00
Excalidraw Bot
d679f40082 New translations en.json (Chinese Simplified) 2024-11-26 23:12:40 +01:00
Excalidraw Bot
9a7cd4f7ef New translations en.json (Russian) 2024-11-26 21:32:27 +01:00
Excalidraw Bot
f94ca28f79 New translations en.json (German) 2024-11-26 20:27:07 +01:00
Excalidraw Bot
f264ae11f4 New translations en.json (Romanian) 2024-11-26 20:27:06 +01:00
Excalidraw Bot
d864979a03 New translations en.json (Karakalpak) 2024-11-26 19:16:20 +01:00
Excalidraw Bot
0a6d3d1adb New translations en.json (Kabyle) 2024-11-26 19:16:19 +01:00
Excalidraw Bot
1d9a5047ad New translations en.json (Bengali, India) 2024-11-26 19:16:18 +01:00
Excalidraw Bot
e3ec60d5f0 New translations en.json (German, Switzerland) 2024-11-26 19:16:16 +01:00
Excalidraw Bot
7d13b85641 New translations en.json (Occitan) 2024-11-26 19:16:15 +01:00
Excalidraw Bot
5d507846bc New translations en.json (Norwegian Bokmal) 2024-11-26 19:16:14 +01:00
Excalidraw Bot
b75e141298 New translations en.json (Uzbek) 2024-11-26 19:16:13 +01:00
Excalidraw Bot
884c74fbb2 New translations en.json (Sinhala) 2024-11-26 19:16:12 +01:00
Excalidraw Bot
bcf4d508f1 New translations en.json (Chinese Traditional, Hong Kong) 2024-11-26 19:16:11 +01:00
Excalidraw Bot
dc539e6820 New translations en.json (Burmese) 2024-11-26 19:16:10 +01:00
Excalidraw Bot
6f2eb61779 New translations en.json (Hindi) 2024-11-26 19:16:08 +01:00
Excalidraw Bot
9f616b80ad New translations en.json (Azerbaijani) 2024-11-26 19:16:07 +01:00
Excalidraw Bot
054616a1cc New translations en.json (Latvian) 2024-11-26 19:16:06 +01:00
Excalidraw Bot
cec851802c New translations en.json (Kazakh) 2024-11-26 19:16:04 +01:00
Excalidraw Bot
3a0185547b New translations en.json (Norwegian Nynorsk) 2024-11-26 19:16:03 +01:00
Excalidraw Bot
3ff94c62d8 New translations en.json (Thai) 2024-11-26 19:16:02 +01:00
Excalidraw Bot
5c389ba4f8 New translations en.json (Marathi) 2024-11-26 19:16:01 +01:00
Excalidraw Bot
17e68174e0 New translations en.json (Bengali) 2024-11-26 19:15:59 +01:00
Excalidraw Bot
e709161793 New translations en.json (Tamil) 2024-11-26 19:15:58 +01:00
Excalidraw Bot
20f73f04d0 New translations en.json (Khmer) 2024-11-26 19:15:57 +01:00
Excalidraw Bot
fbac5eca10 New translations en.json (Persian) 2024-11-26 19:15:55 +01:00
Excalidraw Bot
cad57ed57f New translations en.json (Portuguese, Brazilian) 2024-11-26 19:15:54 +01:00
Excalidraw Bot
4df28ca379 New translations en.json (Galician) 2024-11-26 19:15:53 +01:00
Excalidraw Bot
1a89311bf1 New translations en.json (Vietnamese) 2024-11-26 19:15:52 +01:00
Excalidraw Bot
e419fbf34f New translations en.json (Chinese Traditional) 2024-11-26 19:15:50 +01:00
Excalidraw Bot
84f2ab1730 New translations en.json (Chinese Simplified) 2024-11-26 19:15:49 +01:00
Excalidraw Bot
4d0d230a2a New translations en.json (Ukrainian) 2024-11-26 19:15:48 +01:00
Excalidraw Bot
b1c73bfa1d New translations en.json (Turkish) 2024-11-26 19:15:47 +01:00
Excalidraw Bot
f6b5f846a0 New translations en.json (Swedish) 2024-11-26 19:15:45 +01:00
Excalidraw Bot
db0f79925b New translations en.json (Slovenian) 2024-11-26 19:15:43 +01:00
Excalidraw Bot
f23ba3ef04 New translations en.json (Slovak) 2024-11-26 19:15:42 +01:00
Excalidraw Bot
8c0adc2057 New translations en.json (Russian) 2024-11-26 19:15:41 +01:00
Excalidraw Bot
a9276c6be4 New translations en.json (Portuguese) 2024-11-26 19:15:39 +01:00
Excalidraw Bot
e9239f7cd6 New translations en.json (Polish) 2024-11-26 19:15:38 +01:00
Excalidraw Bot
3607ed03a4 New translations en.json (Punjabi) 2024-11-26 19:15:37 +01:00
Excalidraw Bot
0fbc118070 New translations en.json (Dutch) 2024-11-26 19:15:34 +01:00
Excalidraw Bot
6a620a5384 New translations en.json (Lithuanian) 2024-11-26 19:15:33 +01:00
Excalidraw Bot
c87d215ca7 New translations en.json (Kurdish) 2024-11-26 19:15:32 +01:00
Excalidraw Bot
2a31a1ff29 New translations en.json (Korean) 2024-11-26 19:15:30 +01:00
Excalidraw Bot
cdc50c727e New translations en.json (Japanese) 2024-11-26 19:15:29 +01:00
Excalidraw Bot
73c788b92a New translations en.json (Italian) 2024-11-26 19:15:28 +01:00
Excalidraw Bot
b14ddf04bd New translations en.json (Hungarian) 2024-11-26 19:15:26 +01:00
Excalidraw Bot
2099a5a9ce New translations en.json (Hebrew) 2024-11-26 19:15:25 +01:00
Excalidraw Bot
e645dde8cb New translations en.json (Finnish) 2024-11-26 19:15:23 +01:00
Excalidraw Bot
481c01a2f1 New translations en.json (Basque) 2024-11-26 19:15:22 +01:00
Excalidraw Bot
3cbff07c4d New translations en.json (Greek) 2024-11-26 19:15:21 +01:00
Excalidraw Bot
afff916b38 New translations en.json (German) 2024-11-26 19:15:19 +01:00
Excalidraw Bot
89b4bf9ba9 New translations en.json (Danish) 2024-11-26 19:15:18 +01:00
Excalidraw Bot
0d2c2589ff New translations en.json (Czech) 2024-11-26 19:15:17 +01:00
Excalidraw Bot
8bad0ff2f4 New translations en.json (Bulgarian) 2024-11-26 19:15:15 +01:00
Excalidraw Bot
5f395cb853 New translations en.json (Arabic) 2024-11-26 19:15:14 +01:00
Excalidraw Bot
7fff5d5b81 New translations en.json (Spanish) 2024-11-26 19:15:12 +01:00
Excalidraw Bot
b025fee131 New translations en.json (French) 2024-11-26 19:15:11 +01:00
Excalidraw Bot
be6bed7ef6 New translations en.json (Romanian) 2024-11-26 19:15:10 +01:00
Excalidraw Bot
14d3a5d24c New translations en.json (Indonesian) 2024-11-26 19:15:09 +01:00
Excalidraw Bot
185e8c2872 New translations en.json (Catalan) 2024-11-26 19:15:07 +01:00
Excalidraw Bot
911acf5563 New translations en.json (Indonesian) 2024-11-26 18:06:22 +01:00
Excalidraw Bot
06f4d4bdf6 New translations en.json (Catalan) 2024-11-19 12:11:10 +01:00
Excalidraw Bot
51df6af4d5 New translations en.json (Catalan) 2024-11-19 09:45:38 +01:00
Excalidraw Bot
2b82cfeb17 New translations en.json (Persian) 2024-11-06 16:00:23 +01:00
Excalidraw Bot
45412a5b9f New translations en.json (Persian) 2024-11-06 14:10:19 +01:00
Excalidraw Bot
0d02fe5357 New translations en.json (Portuguese, Brazilian) 2024-11-05 21:43:37 +01:00
Excalidraw Bot
7173691477 New translations en.json (Chinese Simplified) 2024-10-26 12:43:37 +02:00
Excalidraw Bot
48b9a4d5dc New translations en.json (Hindi) 2024-10-24 09:47:16 +02:00
Excalidraw Bot
76dd970ded New translations en.json (Marathi) 2024-10-24 09:47:14 +02:00
Excalidraw Bot
9c963374c1 New translations en.json (Marathi) 2024-10-24 07:40:11 +02:00
Excalidraw Bot
9be077c0af New translations en.json (Polish) 2024-10-23 14:28:30 +02:00
Excalidraw Bot
6980e289ba New translations en.json (Thai) 2024-10-23 13:16:18 +02:00
Excalidraw Bot
4ac09f6b2b New translations en.json (Polish) 2024-10-23 13:16:16 +02:00
Excalidraw Bot
62e9b39ac5 New translations en.json (Chinese Traditional) 2024-10-23 06:40:53 +02:00
Excalidraw Bot
f9b0d26c7f New translations en.json (German) 2024-10-22 19:44:31 +02:00
Excalidraw Bot
43e8ae3bdd New translations en.json (Romanian) 2024-10-22 12:29:39 +02:00
Excalidraw Bot
695c2580cd New translations en.json (Slovenian) 2024-10-22 06:25:46 +02:00
Excalidraw Bot
41a7111e19 New translations en.json (Karakalpak) 2024-10-21 23:42:54 +02:00
Excalidraw Bot
0338f74b45 New translations en.json (Kabyle) 2024-10-21 23:42:53 +02:00
Excalidraw Bot
baa1858a95 New translations en.json (Bengali, India) 2024-10-21 23:42:52 +02:00
Excalidraw Bot
e011b47e58 New translations en.json (German, Switzerland) 2024-10-21 23:42:51 +02:00
Excalidraw Bot
a97c8a0360 New translations en.json (Occitan) 2024-10-21 23:42:50 +02:00
Excalidraw Bot
976ffab80f New translations en.json (Norwegian Bokmal) 2024-10-21 23:42:49 +02:00
Excalidraw Bot
84a363fe4d New translations en.json (Uzbek) 2024-10-21 23:42:48 +02:00
Excalidraw Bot
62d05d7f25 New translations en.json (Sinhala) 2024-10-21 23:42:47 +02:00
Excalidraw Bot
66e5170691 New translations en.json (Chinese Traditional, Hong Kong) 2024-10-21 23:42:46 +02:00
Excalidraw Bot
da16dd3eff New translations en.json (Burmese) 2024-10-21 23:42:44 +02:00
Excalidraw Bot
00f0f85cd8 New translations en.json (Hindi) 2024-10-21 23:42:43 +02:00
Excalidraw Bot
8c864ea97b New translations en.json (Azerbaijani) 2024-10-21 23:42:42 +02:00
Excalidraw Bot
b20083c572 New translations en.json (Latvian) 2024-10-21 23:42:41 +02:00
Excalidraw Bot
c91a774849 New translations en.json (Kazakh) 2024-10-21 23:42:40 +02:00
Excalidraw Bot
835be2ae12 New translations en.json (Norwegian Nynorsk) 2024-10-21 23:42:39 +02:00
Excalidraw Bot
3831c17d45 New translations en.json (Thai) 2024-10-21 23:42:38 +02:00
Excalidraw Bot
3b2779dacc New translations en.json (Marathi) 2024-10-21 23:42:36 +02:00
Excalidraw Bot
31a0a79438 New translations en.json (Bengali) 2024-10-21 23:42:35 +02:00
Excalidraw Bot
310e04cd63 New translations en.json (Tamil) 2024-10-21 23:42:34 +02:00
Excalidraw Bot
ebd84c318d New translations en.json (Khmer) 2024-10-21 23:42:33 +02:00
Excalidraw Bot
3b5a918176 New translations en.json (Persian) 2024-10-21 23:42:32 +02:00
Excalidraw Bot
c878278c4c New translations en.json (Indonesian) 2024-10-21 23:42:31 +02:00
Excalidraw Bot
2fb60ffdd2 New translations en.json (Portuguese, Brazilian) 2024-10-21 23:42:30 +02:00
Excalidraw Bot
3ed09450bf New translations en.json (Galician) 2024-10-21 23:42:29 +02:00
Excalidraw Bot
6ba9228ee1 New translations en.json (Vietnamese) 2024-10-21 23:42:27 +02:00
Excalidraw Bot
9cbc5fe090 New translations en.json (Chinese Traditional) 2024-10-21 23:42:26 +02:00
Excalidraw Bot
4cb605f65e New translations en.json (Ukrainian) 2024-10-21 23:42:25 +02:00
Excalidraw Bot
b9f7b1b927 New translations en.json (Slovenian) 2024-10-21 23:42:24 +02:00
Excalidraw Bot
1ce313ef8d New translations en.json (Russian) 2024-10-21 23:42:23 +02:00
Excalidraw Bot
92f40dee15 New translations en.json (Portuguese) 2024-10-21 23:42:22 +02:00
Excalidraw Bot
349d4336c4 New translations en.json (Polish) 2024-10-21 23:42:21 +02:00
Excalidraw Bot
d678395574 New translations en.json (Punjabi) 2024-10-21 23:42:20 +02:00
Excalidraw Bot
699a08aed7 New translations en.json (Dutch) 2024-10-21 23:42:18 +02:00
Excalidraw Bot
eb17963a56 New translations en.json (Lithuanian) 2024-10-21 23:42:17 +02:00
Excalidraw Bot
0be2c0be9d New translations en.json (Kurdish) 2024-10-21 23:42:16 +02:00
Excalidraw Bot
3e52ed7c45 New translations en.json (Japanese) 2024-10-21 23:42:15 +02:00
Excalidraw Bot
84a89d4f74 New translations en.json (Italian) 2024-10-21 23:42:14 +02:00
Excalidraw Bot
80cc680fff New translations en.json (Hungarian) 2024-10-21 23:42:13 +02:00
Excalidraw Bot
255f47483f New translations en.json (Hebrew) 2024-10-21 23:42:12 +02:00
Excalidraw Bot
10f5c6b509 New translations en.json (Finnish) 2024-10-21 23:42:11 +02:00
Excalidraw Bot
6e0fac82d3 New translations en.json (Basque) 2024-10-21 23:42:10 +02:00
Excalidraw Bot
2be2924fa0 New translations en.json (Greek) 2024-10-21 23:42:09 +02:00
Excalidraw Bot
9fd4565e4a New translations en.json (German) 2024-10-21 23:42:07 +02:00
Excalidraw Bot
4e5ea9c740 New translations en.json (Danish) 2024-10-21 23:42:06 +02:00
Excalidraw Bot
0ab0d44cd3 New translations en.json (Czech) 2024-10-21 23:42:05 +02:00
Excalidraw Bot
6c26b4e569 New translations en.json (Catalan) 2024-10-21 23:42:04 +02:00
Excalidraw Bot
5b0253d3a6 New translations en.json (Bulgarian) 2024-10-21 23:42:03 +02:00
Excalidraw Bot
28a654fccc New translations en.json (Arabic) 2024-10-21 23:42:02 +02:00
Excalidraw Bot
bda68283d3 New translations en.json (Spanish) 2024-10-21 23:42:00 +02:00
Excalidraw Bot
eb7140181d New translations en.json (Romanian) 2024-10-21 23:41:59 +02:00
Excalidraw Bot
9b93b1c568 New translations en.json (French) 2024-10-21 23:41:58 +02:00
Excalidraw Bot
d32aed4330 New translations en.json (Chinese Simplified) 2024-10-21 23:41:57 +02:00
Excalidraw Bot
419f9f2a2f New translations en.json (Korean) 2024-10-21 23:41:56 +02:00
Excalidraw Bot
86dfb3dff2 New translations en.json (Slovak) 2024-10-21 23:41:55 +02:00
Excalidraw Bot
4a650dc607 New translations en.json (Swedish) 2024-10-21 23:41:54 +02:00
Excalidraw Bot
6db2847d10 New translations en.json (Turkish) 2024-10-21 23:41:53 +02:00
Excalidraw Bot
0c24264185 New translations en.json (French) 2024-10-21 17:02:51 +02:00
Excalidraw Bot
9391e8090a New translations en.json (Slovak) 2024-10-20 19:51:59 +02:00
Excalidraw Bot
c0c3ca85d7 New translations en.json (Russian) 2024-10-18 10:39:46 +02:00
Excalidraw Bot
d183629ca4 New translations en.json (Chinese Simplified) 2024-10-18 07:52:05 +02:00
Excalidraw Bot
cd4846f8aa New translations en.json (Chinese Traditional) 2024-10-18 05:37:32 +02:00
Excalidraw Bot
997bd7f6b3 New translations en.json (Polish) 2024-10-17 23:06:53 +02:00
Excalidraw Bot
a93a36c94a New translations en.json (Slovenian) 2024-10-17 21:45:50 +02:00
Excalidraw Bot
84314ed5ec New translations en.json (German) 2024-10-17 21:45:49 +02:00
Excalidraw Bot
ae09870836 New translations en.json (Karakalpak) 2024-10-17 20:17:04 +02:00
Excalidraw Bot
bff8aaee01 New translations en.json (Kabyle) 2024-10-17 20:17:02 +02:00
Excalidraw Bot
b059d9ac0b New translations en.json (Bengali, India) 2024-10-17 20:17:01 +02:00
Excalidraw Bot
46c9b1d2a9 New translations en.json (German, Switzerland) 2024-10-17 20:17:00 +02:00
Excalidraw Bot
3e36e07d80 New translations en.json (Occitan) 2024-10-17 20:16:59 +02:00
Excalidraw Bot
0080bcfce5 New translations en.json (Norwegian Bokmal) 2024-10-17 20:16:58 +02:00
Excalidraw Bot
0bd6ce4b47 New translations en.json (Uzbek) 2024-10-17 20:16:57 +02:00
Excalidraw Bot
f4c88d5669 New translations en.json (Sinhala) 2024-10-17 20:16:56 +02:00
Excalidraw Bot
b6038126c5 New translations en.json (Chinese Traditional, Hong Kong) 2024-10-17 20:16:55 +02:00
Excalidraw Bot
5ab897112c New translations en.json (Burmese) 2024-10-17 20:16:54 +02:00
Excalidraw Bot
1b2d4e59a3 New translations en.json (Hindi) 2024-10-17 20:16:53 +02:00
Excalidraw Bot
569860cde6 New translations en.json (Azerbaijani) 2024-10-17 20:16:51 +02:00
Excalidraw Bot
7de2e0975d New translations en.json (Latvian) 2024-10-17 20:16:50 +02:00
Excalidraw Bot
653bcd7898 New translations en.json (Kazakh) 2024-10-17 20:16:49 +02:00
Excalidraw Bot
733b0b45ce New translations en.json (Norwegian Nynorsk) 2024-10-17 20:16:48 +02:00
Excalidraw Bot
ed2c4ccbba New translations en.json (Thai) 2024-10-17 20:16:47 +02:00
Excalidraw Bot
aab15eef3e New translations en.json (Marathi) 2024-10-17 20:16:45 +02:00
Excalidraw Bot
ce7ede5fb0 New translations en.json (Bengali) 2024-10-17 20:16:44 +02:00
Excalidraw Bot
944ffba66f New translations en.json (Tamil) 2024-10-17 20:16:43 +02:00
Excalidraw Bot
e600142ee6 New translations en.json (Khmer) 2024-10-17 20:16:42 +02:00
Excalidraw Bot
3a3e9f8701 New translations en.json (Persian) 2024-10-17 20:16:40 +02:00
Excalidraw Bot
dfdfeae79f New translations en.json (Indonesian) 2024-10-17 20:16:39 +02:00
Excalidraw Bot
a6b49fa014 New translations en.json (Portuguese, Brazilian) 2024-10-17 20:16:38 +02:00
Excalidraw Bot
a706962edd New translations en.json (Galician) 2024-10-17 20:16:37 +02:00
Excalidraw Bot
e69fd9f2f8 New translations en.json (Vietnamese) 2024-10-17 20:16:36 +02:00
Excalidraw Bot
3f7b5034e7 New translations en.json (Chinese Traditional) 2024-10-17 20:16:35 +02:00
Excalidraw Bot
fcbecec034 New translations en.json (Ukrainian) 2024-10-17 20:16:34 +02:00
Excalidraw Bot
e77fc90d90 New translations en.json (Slovenian) 2024-10-17 20:16:32 +02:00
Excalidraw Bot
112b16d9df New translations en.json (Russian) 2024-10-17 20:16:30 +02:00
Excalidraw Bot
dc4e625750 New translations en.json (Portuguese) 2024-10-17 20:16:29 +02:00
Excalidraw Bot
a25eae3edd New translations en.json (Polish) 2024-10-17 20:16:28 +02:00
Excalidraw Bot
7f58444112 New translations en.json (Punjabi) 2024-10-17 20:16:27 +02:00
Excalidraw Bot
6527ee5a11 New translations en.json (Dutch) 2024-10-17 20:16:25 +02:00
Excalidraw Bot
52a2558d11 New translations en.json (Lithuanian) 2024-10-17 20:16:24 +02:00
Excalidraw Bot
21a56e4a0b New translations en.json (Kurdish) 2024-10-17 20:16:23 +02:00
Excalidraw Bot
c2fdeda13e New translations en.json (Japanese) 2024-10-17 20:16:22 +02:00
Excalidraw Bot
4e0f644a55 New translations en.json (Italian) 2024-10-17 20:16:21 +02:00
Excalidraw Bot
257ffe1c07 New translations en.json (Hungarian) 2024-10-17 20:16:20 +02:00
Excalidraw Bot
5416ee4c7c New translations en.json (Hebrew) 2024-10-17 20:16:19 +02:00
Excalidraw Bot
833314cf7a New translations en.json (Finnish) 2024-10-17 20:16:17 +02:00
Excalidraw Bot
359c2c2bc6 New translations en.json (Basque) 2024-10-17 20:16:16 +02:00
Excalidraw Bot
e8e734be56 New translations en.json (Greek) 2024-10-17 20:16:15 +02:00
Excalidraw Bot
556e38edce New translations en.json (German) 2024-10-17 20:16:14 +02:00
Excalidraw Bot
aaeddcf0e1 New translations en.json (Danish) 2024-10-17 20:16:13 +02:00
Excalidraw Bot
6139cb6d98 New translations en.json (Czech) 2024-10-17 20:16:12 +02:00
Excalidraw Bot
aff50136ef New translations en.json (Catalan) 2024-10-17 20:16:11 +02:00
Excalidraw Bot
8a8c60adab New translations en.json (Bulgarian) 2024-10-17 20:16:09 +02:00
Excalidraw Bot
c09b46e964 New translations en.json (Arabic) 2024-10-17 20:16:08 +02:00
Excalidraw Bot
ed7ffe00a3 New translations en.json (Spanish) 2024-10-17 20:16:07 +02:00
Excalidraw Bot
67b8e63637 New translations en.json (Romanian) 2024-10-17 20:16:06 +02:00
Excalidraw Bot
c6a8e4de1e New translations en.json (French) 2024-10-17 20:16:05 +02:00
Excalidraw Bot
59982f4d84 New translations en.json (Chinese Simplified) 2024-10-17 20:16:04 +02:00
Excalidraw Bot
ab6e573497 New translations en.json (Korean) 2024-10-17 20:16:02 +02:00
Excalidraw Bot
dd377b2a0f New translations en.json (Slovak) 2024-10-17 20:16:01 +02:00
Excalidraw Bot
c6607c4d19 New translations en.json (Swedish) 2024-10-17 20:16:00 +02:00
Excalidraw Bot
f881d98ae7 New translations en.json (Turkish) 2024-10-17 20:15:59 +02:00
Excalidraw Bot
7a88e72f82 New translations en.json (French) 2024-10-15 13:15:42 +02:00
Excalidraw Bot
d132221f9f New translations en.json (Chinese Simplified) 2024-10-14 05:51:53 +02:00
Excalidraw Bot
46a7204d41 New translations en.json (Korean) 2024-10-12 10:18:26 +02:00
Excalidraw Bot
c46038b47e New translations en.json (Korean) 2024-10-12 09:08:57 +02:00
Excalidraw Bot
1ec6828470 New translations en.json (Slovak) 2024-10-05 09:29:19 +02:00
Excalidraw Bot
8d5d10b352 New translations en.json (Swedish) 2024-10-04 16:47:21 +02:00
Excalidraw Bot
09585d312b New translations en.json (Swedish) 2024-10-04 15:02:33 +02:00
Excalidraw Bot
7e8b2ad87e New translations en.json (Turkish) 2024-10-03 15:45:15 +02:00
Excalidraw Bot
26c6bd8942 New translations en.json (Portuguese, Brazilian) 2024-10-01 18:35:44 +02:00
Excalidraw Bot
d198280f6c New translations en.json (Chinese Simplified) 2024-09-26 12:55:03 +02:00
Excalidraw Bot
573adc72a2 New translations en.json (Japanese) 2024-09-26 12:55:01 +02:00
Excalidraw Bot
94dcc50578 New translations en.json (Hebrew) 2024-09-20 11:33:55 +02:00
Excalidraw Bot
1b8591d297 New translations en.json (Hebrew) 2024-09-20 09:16:14 +02:00
Excalidraw Bot
a3afb5551b New translations en.json (Chinese Traditional) 2024-09-16 05:50:12 +02:00
Excalidraw Bot
cda10a8aff New translations en.json (Persian) 2024-09-13 23:05:05 +02:00
Excalidraw Bot
a0d7a0a178 New translations en.json (Polish) 2024-09-12 18:49:55 +02:00
Excalidraw Bot
c94e69abbb New translations en.json (Polish) 2024-09-12 15:08:27 +02:00
Excalidraw Bot
c1227e5e65 New translations en.json (Ukrainian) 2024-09-12 14:10:48 +02:00
Excalidraw Bot
f535d1a2c1 New translations en.json (Hindi) 2024-09-12 08:06:48 +02:00
Excalidraw Bot
a2be6780de New translations en.json (Marathi) 2024-09-12 08:06:47 +02:00
Excalidraw Bot
fc174d14c4 New translations en.json (Hindi) 2024-09-12 07:08:04 +02:00
Excalidraw Bot
69fef3808b New translations en.json (Marathi) 2024-09-12 07:08:03 +02:00
Excalidraw Bot
d63e67f1ef New translations en.json (Russian) 2024-09-11 22:32:08 +02:00
Excalidraw Bot
bbbde64199 New translations en.json (Slovenian) 2024-09-11 20:55:49 +02:00
Excalidraw Bot
136eb8bbad New translations en.json (German) 2024-09-11 20:55:47 +02:00
Excalidraw Bot
220952d014 New translations en.json (Romanian) 2024-09-11 20:55:46 +02:00
Excalidraw Bot
789ccd857a New translations en.json (Hindi) 2024-09-11 19:34:29 +02:00
Excalidraw Bot
4270b2c013 New translations en.json (Marathi) 2024-09-11 19:34:24 +02:00
Excalidraw Bot
98f432ff8e New translations en.json (Chinese Traditional) 2024-09-11 19:34:19 +02:00
Excalidraw Bot
3aeb0dde1f New translations en.json (Swedish) 2024-09-11 19:34:15 +02:00
Excalidraw Bot
a6e3e4c1d9 New translations en.json (Slovenian) 2024-09-11 19:34:14 +02:00
Excalidraw Bot
34defc0327 New translations en.json (Russian) 2024-09-11 19:34:13 +02:00
Excalidraw Bot
a76508746a New translations en.json (Portuguese) 2024-09-11 19:34:12 +02:00
Excalidraw Bot
624c80e80a New translations en.json (German) 2024-09-11 19:34:03 +02:00
Excalidraw Bot
0f695e41e1 New translations en.json (Romanian) 2024-09-11 19:33:58 +02:00
Excalidraw Bot
13dbb4fcc5 New translations en.json (Polish) 2024-09-11 19:33:56 +02:00
Excalidraw Bot
59d5d7e0b5 New translations en.json (German, Switzerland) 2024-09-11 19:33:55 +02:00
Excalidraw Bot
8f6323fd38 New translations en.json (Hindi) 2024-09-11 11:46:51 +02:00
Excalidraw Bot
4f5ba867be New translations en.json (Marathi) 2024-09-11 11:46:49 +02:00
Excalidraw Bot
2ff791a31b New translations en.json (Polish) 2024-09-11 11:46:48 +02:00
Excalidraw Bot
678b8edb87 New translations en.json (Romanian) 2024-09-10 21:20:50 +02:00
Excalidraw Bot
6e29b3ad25 New translations en.json (Swedish) 2024-09-10 09:34:34 +02:00
Excalidraw Bot
31e812c084 New translations en.json (Slovenian) 2024-09-10 09:34:32 +02:00
Excalidraw Bot
4b3dd5ba71 New translations en.json (Chinese Traditional) 2024-09-10 06:19:12 +02:00
Excalidraw Bot
941219be23 New translations en.json (Russian) 2024-09-09 23:40:22 +02:00
Excalidraw Bot
c74ee59fee New translations en.json (Portuguese) 2024-09-09 21:08:26 +02:00
Excalidraw Bot
b35bcdb09e New translations en.json (German) 2024-09-09 19:49:08 +02:00
Excalidraw Bot
e3fdaf7e9d New translations en.json (Karakalpak) 2024-09-09 17:31:44 +02:00
Excalidraw Bot
55b438017f New translations en.json (Kabyle) 2024-09-09 17:31:43 +02:00
Excalidraw Bot
52a95589d6 New translations en.json (Bengali, India) 2024-09-09 17:31:42 +02:00
Excalidraw Bot
e1351768c8 New translations en.json (Occitan) 2024-09-09 17:31:40 +02:00
Excalidraw Bot
03867d184a New translations en.json (Norwegian Bokmal) 2024-09-09 17:31:39 +02:00
Excalidraw Bot
63511c149a New translations en.json (Uzbek) 2024-09-09 17:31:38 +02:00
Excalidraw Bot
28aa841d8e New translations en.json (Sinhala) 2024-09-09 17:31:35 +02:00
Excalidraw Bot
cbd1d07c91 New translations en.json (Chinese Traditional, Hong Kong) 2024-09-09 17:31:34 +02:00
Excalidraw Bot
b8add8f2ed New translations en.json (Burmese) 2024-09-09 17:31:33 +02:00
Excalidraw Bot
632e9d492f New translations en.json (Hindi) 2024-09-09 17:31:32 +02:00
Excalidraw Bot
5f848e58c3 New translations en.json (Azerbaijani) 2024-09-09 17:31:31 +02:00
Excalidraw Bot
f67c30d062 New translations en.json (Latvian) 2024-09-09 17:31:29 +02:00
Excalidraw Bot
195b05cd44 New translations en.json (Kazakh) 2024-09-09 17:31:28 +02:00
Excalidraw Bot
09ebef19dd New translations en.json (Norwegian Nynorsk) 2024-09-09 17:31:27 +02:00
Excalidraw Bot
d465b5df2a New translations en.json (Thai) 2024-09-09 17:31:26 +02:00
Excalidraw Bot
8a88c67b60 New translations en.json (Marathi) 2024-09-09 17:31:24 +02:00
Excalidraw Bot
4f3acdee72 New translations en.json (Bengali) 2024-09-09 17:31:23 +02:00
Excalidraw Bot
dab9274cdd New translations en.json (Tamil) 2024-09-09 17:31:22 +02:00
Excalidraw Bot
b0991c13d9 New translations en.json (Khmer) 2024-09-09 17:31:21 +02:00
Excalidraw Bot
0d727dd01a New translations en.json (Indonesian) 2024-09-09 17:31:20 +02:00
Excalidraw Bot
d4b6a1a89c New translations en.json (Portuguese, Brazilian) 2024-09-09 17:31:19 +02:00
Excalidraw Bot
425736cb55 New translations en.json (Galician) 2024-09-09 17:31:18 +02:00
Excalidraw Bot
094f35e1a1 New translations en.json (Vietnamese) 2024-09-09 17:31:17 +02:00
Excalidraw Bot
6f93afcbd7 New translations en.json (Chinese Traditional) 2024-09-09 17:31:16 +02:00
Excalidraw Bot
71678ed812 New translations en.json (Chinese Simplified) 2024-09-09 17:31:14 +02:00
Excalidraw Bot
d19c45d42c New translations en.json (Ukrainian) 2024-09-09 17:31:13 +02:00
Excalidraw Bot
9d29320bc0 New translations en.json (Turkish) 2024-09-09 17:31:12 +02:00
Excalidraw Bot
f083ba7f8d New translations en.json (Swedish) 2024-09-09 17:31:11 +02:00
Excalidraw Bot
bfa4205bf7 New translations en.json (Slovenian) 2024-09-09 17:31:10 +02:00
Excalidraw Bot
c4d3cb7d4e New translations en.json (Slovak) 2024-09-09 17:31:09 +02:00
Excalidraw Bot
1fe128e53b New translations en.json (Russian) 2024-09-09 17:31:07 +02:00
Excalidraw Bot
25f3c1486c New translations en.json (Portuguese) 2024-09-09 17:31:06 +02:00
Excalidraw Bot
620f837b82 New translations en.json (Punjabi) 2024-09-09 17:31:05 +02:00
Excalidraw Bot
65a58cb080 New translations en.json (Dutch) 2024-09-09 17:31:04 +02:00
Excalidraw Bot
f9d9d8eefc New translations en.json (Lithuanian) 2024-09-09 17:31:03 +02:00
Excalidraw Bot
5f5d8dea8a New translations en.json (Kurdish) 2024-09-09 17:31:01 +02:00
Excalidraw Bot
230827cba5 New translations en.json (Korean) 2024-09-09 17:31:00 +02:00
Excalidraw Bot
53c7487113 New translations en.json (Japanese) 2024-09-09 17:30:59 +02:00
Excalidraw Bot
d5b4287f41 New translations en.json (Italian) 2024-09-09 17:30:58 +02:00
Excalidraw Bot
c29b7a5c7a New translations en.json (Hungarian) 2024-09-09 17:30:57 +02:00
Excalidraw Bot
a56dd2a529 New translations en.json (Hebrew) 2024-09-09 17:30:55 +02:00
Excalidraw Bot
14b59805a2 New translations en.json (Finnish) 2024-09-09 17:30:54 +02:00
Excalidraw Bot
e01e1be3de New translations en.json (Basque) 2024-09-09 17:30:53 +02:00
Excalidraw Bot
d403251fd7 New translations en.json (German) 2024-09-09 17:30:52 +02:00
Excalidraw Bot
d46c9d35b7 New translations en.json (Danish) 2024-09-09 17:30:51 +02:00
Excalidraw Bot
5fa9193415 New translations en.json (Czech) 2024-09-09 17:30:50 +02:00
Excalidraw Bot
239767be22 New translations en.json (Catalan) 2024-09-09 17:30:49 +02:00
Excalidraw Bot
7ce49d3566 New translations en.json (Bulgarian) 2024-09-09 17:30:48 +02:00
Excalidraw Bot
e228cca96b New translations en.json (Arabic) 2024-09-09 17:30:47 +02:00
Excalidraw Bot
92f2b0b0e1 New translations en.json (Spanish) 2024-09-09 17:30:45 +02:00
Excalidraw Bot
01d1639141 New translations en.json (French) 2024-09-09 17:30:44 +02:00
Excalidraw Bot
11272a101f New translations en.json (Romanian) 2024-09-09 17:30:43 +02:00
Excalidraw Bot
d2bdb7ab0b New translations en.json (Greek) 2024-09-09 17:30:42 +02:00
Excalidraw Bot
bc0d3b1a67 New translations en.json (Polish) 2024-09-09 17:30:41 +02:00
Excalidraw Bot
e2451d9c7f New translations en.json (German, Switzerland) 2024-09-09 17:30:40 +02:00
Excalidraw Bot
670887e3f3 New translations en.json (Persian) 2024-09-09 17:30:38 +02:00
Excalidraw Bot
345e3535b4 New translations en.json (Slovak) 2024-09-05 15:45:17 +02:00
Excalidraw Bot
5eeeba0333 New translations en.json (Hebrew) 2024-09-03 23:55:19 +02:00
Excalidraw Bot
df351f3b30 New translations en.json (Portuguese) 2024-09-03 19:33:06 +02:00
Excalidraw Bot
29d5da3e66 New translations en.json (French) 2024-09-03 11:35:20 +02:00
Excalidraw Bot
12d35d3da3 New translations en.json (Ukrainian) 2024-08-31 17:08:12 +02:00
Excalidraw Bot
a067dd0faa New translations en.json (Greek) 2024-08-31 13:53:33 +02:00
Excalidraw Bot
4758d28ac1 New translations en.json (Portuguese, Brazilian) 2024-08-31 07:10:40 +02:00
Excalidraw Bot
bfc9692ad1 New translations en.json (Italian) 2024-08-30 14:42:21 +02:00
Excalidraw Bot
a23fef8afe New translations en.json (Chinese Traditional) 2024-08-28 16:34:09 +02:00
Excalidraw Bot
2827117eb4 New translations en.json (Polish) 2024-08-27 22:22:10 +02:00
Excalidraw Bot
e11d71d9c1 New translations en.json (German) 2024-08-27 13:48:03 +02:00
Excalidraw Bot
0aacafc032 New translations en.json (Romanian) 2024-08-27 11:46:25 +02:00
Excalidraw Bot
573e947b31 New translations en.json (Russian) 2024-08-27 10:37:45 +02:00
Excalidraw Bot
128e5a0ef0 New translations en.json (Hindi) 2024-08-27 08:40:04 +02:00
Excalidraw Bot
114033dde4 New translations en.json (Marathi) 2024-08-27 08:40:03 +02:00
Excalidraw Bot
3cc0f2e452 New translations en.json (Slovenian) 2024-08-27 08:40:01 +02:00
Excalidraw Bot
28a08686a8 New translations en.json (Russian) 2024-08-27 08:40:00 +02:00
Excalidraw Bot
100e47307b New translations en.json (Chinese Simplified) 2024-08-27 06:53:14 +02:00
Excalidraw Bot
254e6f4d30 New translations en.json (Karakalpak) 2024-08-27 00:32:35 +02:00
Excalidraw Bot
d63d5a2602 New translations en.json (Kabyle) 2024-08-27 00:32:34 +02:00
Excalidraw Bot
729cdc0c2b New translations en.json (Bengali, India) 2024-08-27 00:32:33 +02:00
Excalidraw Bot
253ac4af2d New translations en.json (Occitan) 2024-08-27 00:32:32 +02:00
Excalidraw Bot
63863f2530 New translations en.json (Norwegian Bokmal) 2024-08-27 00:32:31 +02:00
Excalidraw Bot
3bd04e55ab New translations en.json (Uzbek) 2024-08-27 00:32:30 +02:00
Excalidraw Bot
8fd9b5c791 New translations en.json (Sinhala) 2024-08-27 00:32:29 +02:00
Excalidraw Bot
3c7671f160 New translations en.json (Chinese Traditional, Hong Kong) 2024-08-27 00:32:28 +02:00
Excalidraw Bot
16b50fad38 New translations en.json (Burmese) 2024-08-27 00:32:27 +02:00
Excalidraw Bot
a09bd51978 New translations en.json (Hindi) 2024-08-27 00:32:26 +02:00
Excalidraw Bot
829624199b New translations en.json (Azerbaijani) 2024-08-27 00:32:25 +02:00
Excalidraw Bot
3fa3460d1a New translations en.json (Latvian) 2024-08-27 00:32:24 +02:00
Excalidraw Bot
309c1252a6 New translations en.json (Kazakh) 2024-08-27 00:32:23 +02:00
Excalidraw Bot
444673a54e New translations en.json (Norwegian Nynorsk) 2024-08-27 00:32:22 +02:00
Excalidraw Bot
0f58f4dbeb New translations en.json (Thai) 2024-08-27 00:32:21 +02:00
Excalidraw Bot
bbb4d88c2a New translations en.json (Marathi) 2024-08-27 00:32:20 +02:00
Excalidraw Bot
ad0964116a New translations en.json (Bengali) 2024-08-27 00:32:19 +02:00
Excalidraw Bot
91a58912ce New translations en.json (Tamil) 2024-08-27 00:32:18 +02:00
Excalidraw Bot
2c8a913770 New translations en.json (Khmer) 2024-08-27 00:32:17 +02:00
Excalidraw Bot
c37b4ee3f7 New translations en.json (Indonesian) 2024-08-27 00:32:16 +02:00
Excalidraw Bot
85726121a8 New translations en.json (Portuguese, Brazilian) 2024-08-27 00:32:15 +02:00
Excalidraw Bot
1b65578c44 New translations en.json (Galician) 2024-08-27 00:32:14 +02:00
Excalidraw Bot
24fe9663f0 New translations en.json (Vietnamese) 2024-08-27 00:32:13 +02:00
Excalidraw Bot
a54bccf04e New translations en.json (Chinese Traditional) 2024-08-27 00:32:12 +02:00
Excalidraw Bot
50777b6b43 New translations en.json (Chinese Simplified) 2024-08-27 00:32:11 +02:00
Excalidraw Bot
fde9dfe20f New translations en.json (Ukrainian) 2024-08-27 00:32:10 +02:00
Excalidraw Bot
d2ddce8012 New translations en.json (Turkish) 2024-08-27 00:32:09 +02:00
Excalidraw Bot
09a3831733 New translations en.json (Swedish) 2024-08-27 00:32:07 +02:00
Excalidraw Bot
a036419535 New translations en.json (Slovenian) 2024-08-27 00:32:06 +02:00
Excalidraw Bot
e278d51713 New translations en.json (Slovak) 2024-08-27 00:32:05 +02:00
Excalidraw Bot
fcfafce65b New translations en.json (Russian) 2024-08-27 00:32:04 +02:00
Excalidraw Bot
886eb2c588 New translations en.json (Portuguese) 2024-08-27 00:32:03 +02:00
Excalidraw Bot
cfa71f5045 New translations en.json (Punjabi) 2024-08-27 00:32:02 +02:00
Excalidraw Bot
f5c100ed62 New translations en.json (Dutch) 2024-08-27 00:32:01 +02:00
Excalidraw Bot
bd6f81b088 New translations en.json (Lithuanian) 2024-08-27 00:32:00 +02:00
Excalidraw Bot
13f2105589 New translations en.json (Kurdish) 2024-08-27 00:31:59 +02:00
Excalidraw Bot
80e9e037ea New translations en.json (Korean) 2024-08-27 00:31:58 +02:00
Excalidraw Bot
98a6ea7e3a New translations en.json (Japanese) 2024-08-27 00:31:57 +02:00
Excalidraw Bot
83b72ace65 New translations en.json (Italian) 2024-08-27 00:31:56 +02:00
Excalidraw Bot
406fb15bd9 New translations en.json (Hungarian) 2024-08-27 00:31:55 +02:00
Excalidraw Bot
a50b9be1de New translations en.json (Hebrew) 2024-08-27 00:31:54 +02:00
Excalidraw Bot
71cc6a3bfd New translations en.json (Finnish) 2024-08-27 00:31:53 +02:00
Excalidraw Bot
ec99637bb2 New translations en.json (Basque) 2024-08-27 00:31:52 +02:00
Excalidraw Bot
5d4ee260b3 New translations en.json (German) 2024-08-27 00:31:51 +02:00
Excalidraw Bot
32e295ed8c New translations en.json (Danish) 2024-08-27 00:31:50 +02:00
Excalidraw Bot
c22843a7f1 New translations en.json (Czech) 2024-08-27 00:31:49 +02:00
Excalidraw Bot
be155a676f New translations en.json (Catalan) 2024-08-27 00:31:48 +02:00
Excalidraw Bot
7288582ef2 New translations en.json (Bulgarian) 2024-08-27 00:31:47 +02:00
Excalidraw Bot
e1376f3f74 New translations en.json (Arabic) 2024-08-27 00:31:46 +02:00
Excalidraw Bot
7f25d2f5b5 New translations en.json (Spanish) 2024-08-27 00:31:45 +02:00
Excalidraw Bot
e36f9f56d0 New translations en.json (French) 2024-08-27 00:31:44 +02:00
Excalidraw Bot
2cf88adca9 New translations en.json (Romanian) 2024-08-27 00:31:43 +02:00
Excalidraw Bot
07ad3271b4 New translations en.json (Greek) 2024-08-27 00:31:42 +02:00
Excalidraw Bot
6861334dad New translations en.json (Polish) 2024-08-27 00:31:41 +02:00
Excalidraw Bot
fbc27a7fd1 New translations en.json (German, Switzerland) 2024-08-27 00:31:40 +02:00
Excalidraw Bot
557aa9fa33 New translations en.json (Persian) 2024-08-27 00:31:39 +02:00
Excalidraw Bot
376c7590b5 New translations en.json (Catalan) 2024-08-21 08:56:29 +02:00
Excalidraw Bot
f258ab3a4e New translations en.json (Karakalpak) 2024-08-20 18:38:10 +02:00
Excalidraw Bot
c4f6ff7acc New translations en.json (Kabyle) 2024-08-20 18:38:09 +02:00
Excalidraw Bot
b0e7b86670 New translations en.json (Bengali, India) 2024-08-20 18:38:08 +02:00
Excalidraw Bot
723e1f7b78 New translations en.json (Occitan) 2024-08-20 18:38:07 +02:00
Excalidraw Bot
e6ac11c33d New translations en.json (Norwegian Bokmal) 2024-08-20 18:38:06 +02:00
Excalidraw Bot
fbc5f0460d New translations en.json (Uzbek) 2024-08-20 18:38:05 +02:00
Excalidraw Bot
4c81264c8c New translations en.json (Sinhala) 2024-08-20 18:38:04 +02:00
Excalidraw Bot
fd6750f4cf New translations en.json (Chinese Traditional, Hong Kong) 2024-08-20 18:38:02 +02:00
Excalidraw Bot
c5fed6cdf1 New translations en.json (Burmese) 2024-08-20 18:38:01 +02:00
Excalidraw Bot
4e9f6f3e0e New translations en.json (Hindi) 2024-08-20 18:38:00 +02:00
Excalidraw Bot
b9b37c2b33 New translations en.json (Azerbaijani) 2024-08-20 18:37:59 +02:00
Excalidraw Bot
679a293a18 New translations en.json (Latvian) 2024-08-20 18:37:58 +02:00
Excalidraw Bot
d51dca6c40 New translations en.json (Kazakh) 2024-08-20 18:37:57 +02:00
Excalidraw Bot
a0f0aaab05 New translations en.json (Norwegian Nynorsk) 2024-08-20 18:37:55 +02:00
Excalidraw Bot
5af4b4e7ce New translations en.json (Thai) 2024-08-20 18:37:54 +02:00
Excalidraw Bot
c688d4cbe4 New translations en.json (Marathi) 2024-08-20 18:37:53 +02:00
Excalidraw Bot
c98d4795fb New translations en.json (Bengali) 2024-08-20 18:37:52 +02:00
Excalidraw Bot
c3ceace600 New translations en.json (Tamil) 2024-08-20 18:37:51 +02:00
Excalidraw Bot
3dd2ef328c New translations en.json (Khmer) 2024-08-20 18:37:50 +02:00
Excalidraw Bot
1f75307d2f New translations en.json (Indonesian) 2024-08-20 18:37:48 +02:00
Excalidraw Bot
b1b1cacddf New translations en.json (Portuguese, Brazilian) 2024-08-20 18:37:47 +02:00
Excalidraw Bot
ed564b64ec New translations en.json (Galician) 2024-08-20 18:37:46 +02:00
Excalidraw Bot
6eb4c1e59f New translations en.json (Vietnamese) 2024-08-20 18:37:45 +02:00
Excalidraw Bot
4009c4d69c New translations en.json (Chinese Traditional) 2024-08-20 18:37:44 +02:00
Excalidraw Bot
c143334183 New translations en.json (Chinese Simplified) 2024-08-20 18:37:43 +02:00
Excalidraw Bot
bddacee80d New translations en.json (Ukrainian) 2024-08-20 18:37:42 +02:00
Excalidraw Bot
e6d5fa793d New translations en.json (Turkish) 2024-08-20 18:37:40 +02:00
Excalidraw Bot
ffc0752cba New translations en.json (Swedish) 2024-08-20 18:37:39 +02:00
Excalidraw Bot
a8de15517a New translations en.json (Slovenian) 2024-08-20 18:37:38 +02:00
Excalidraw Bot
a6fb388f5d New translations en.json (Slovak) 2024-08-20 18:37:37 +02:00
Excalidraw Bot
1a61e8f98a New translations en.json (Russian) 2024-08-20 18:37:35 +02:00
Excalidraw Bot
defbbc327c New translations en.json (Portuguese) 2024-08-20 18:37:34 +02:00
Excalidraw Bot
12f5d3c516 New translations en.json (Punjabi) 2024-08-20 18:37:33 +02:00
Excalidraw Bot
045f75161e New translations en.json (Dutch) 2024-08-20 18:37:32 +02:00
Excalidraw Bot
dfcbfaf155 New translations en.json (Lithuanian) 2024-08-20 18:37:31 +02:00
Excalidraw Bot
d233f3b60f New translations en.json (Kurdish) 2024-08-20 18:37:30 +02:00
Excalidraw Bot
b4e84e1cb9 New translations en.json (Korean) 2024-08-20 18:37:29 +02:00
Excalidraw Bot
630991b85a New translations en.json (Japanese) 2024-08-20 18:37:27 +02:00
Excalidraw Bot
2afbb7b0cd New translations en.json (Italian) 2024-08-20 18:37:26 +02:00
Excalidraw Bot
e95f4bd56a New translations en.json (Hungarian) 2024-08-20 18:37:25 +02:00
Excalidraw Bot
88b7830aa7 New translations en.json (Hebrew) 2024-08-20 18:37:24 +02:00
Excalidraw Bot
035d6b8b95 New translations en.json (Finnish) 2024-08-20 18:37:22 +02:00
Excalidraw Bot
d3f1d67e82 New translations en.json (Basque) 2024-08-20 18:37:21 +02:00
Excalidraw Bot
27b3e5ad99 New translations en.json (German) 2024-08-20 18:37:20 +02:00
Excalidraw Bot
7512deca3d New translations en.json (Danish) 2024-08-20 18:37:19 +02:00
Excalidraw Bot
66eaa610d1 New translations en.json (Czech) 2024-08-20 18:37:17 +02:00
Excalidraw Bot
6e4dcd4829 New translations en.json (Catalan) 2024-08-20 18:37:16 +02:00
Excalidraw Bot
d24c462d1c New translations en.json (Bulgarian) 2024-08-20 18:37:14 +02:00
Excalidraw Bot
070b693163 New translations en.json (Arabic) 2024-08-20 18:37:13 +02:00
Excalidraw Bot
12c697a67c New translations en.json (Spanish) 2024-08-20 18:37:11 +02:00
Excalidraw Bot
8e260bb8f0 New translations en.json (French) 2024-08-20 18:37:09 +02:00
Excalidraw Bot
62c096deb2 New translations en.json (Romanian) 2024-08-20 18:37:08 +02:00
Excalidraw Bot
afddbd88c6 New translations en.json (Greek) 2024-08-20 18:37:06 +02:00
Excalidraw Bot
e907c2cb98 New translations en.json (Polish) 2024-08-20 18:37:05 +02:00
Excalidraw Bot
4f1df9a3bf New translations en.json (German, Switzerland) 2024-08-20 18:37:03 +02:00
Excalidraw Bot
3ac658dd26 New translations en.json (Persian) 2024-08-20 18:37:01 +02:00
Excalidraw Bot
1c5581be0d New translations en.json (Portuguese) 2024-08-20 16:04:08 +02:00
Excalidraw Bot
6a0a34e0e7 New translations en.json (Vietnamese) 2024-08-18 16:30:42 +02:00
Excalidraw Bot
f560a7da67 New translations en.json (Greek) 2024-08-15 21:43:42 +02:00
Excalidraw Bot
2d4f69f83f New translations en.json (Chinese Simplified) 2024-08-13 07:18:53 +02:00
Excalidraw Bot
c124d99010 New translations en.json (Swedish) 2024-08-13 07:18:52 +02:00
Excalidraw Bot
59e5678151 New translations en.json (Polish) 2024-08-12 13:40:48 +02:00
Excalidraw Bot
a179dd38cf New translations en.json (Chinese Traditional) 2024-08-12 11:58:44 +02:00
Excalidraw Bot
e014ffb5b3 New translations en.json (Romanian) 2024-08-12 09:54:49 +02:00
Excalidraw Bot
21453a4858 New translations en.json (Slovenian) 2024-08-11 21:52:58 +02:00
Excalidraw Bot
58b78e0744 New translations en.json (German) 2024-08-11 21:52:57 +02:00
Excalidraw Bot
ba14b526ab New translations en.json (Polish) 2024-08-11 20:55:44 +02:00
Excalidraw Bot
3aacd5baba New translations en.json (Karakalpak) 2024-08-11 19:53:34 +02:00
Excalidraw Bot
4625f1f01a New translations en.json (Kabyle) 2024-08-11 19:53:33 +02:00
Excalidraw Bot
8395c84aa9 New translations en.json (Bengali, India) 2024-08-11 19:53:32 +02:00
Excalidraw Bot
ee6d0a2a2c New translations en.json (Occitan) 2024-08-11 19:53:31 +02:00
Excalidraw Bot
0d91a3ee98 New translations en.json (Norwegian Bokmal) 2024-08-11 19:53:30 +02:00
Excalidraw Bot
5036bac094 New translations en.json (Uzbek) 2024-08-11 19:53:29 +02:00
Excalidraw Bot
b82556aafd New translations en.json (Sinhala) 2024-08-11 19:53:27 +02:00
Excalidraw Bot
50d04b5802 New translations en.json (Chinese Traditional, Hong Kong) 2024-08-11 19:53:26 +02:00
Excalidraw Bot
fd917664e7 New translations en.json (Burmese) 2024-08-11 19:53:25 +02:00
Excalidraw Bot
b3da75f525 New translations en.json (Hindi) 2024-08-11 19:53:23 +02:00
Excalidraw Bot
93d61a66c1 New translations en.json (Azerbaijani) 2024-08-11 19:53:22 +02:00
Excalidraw Bot
bed4fb9556 New translations en.json (Latvian) 2024-08-11 19:53:21 +02:00
Excalidraw Bot
7567ea5b20 New translations en.json (Kazakh) 2024-08-11 19:53:20 +02:00
Excalidraw Bot
964c253fb8 New translations en.json (Norwegian Nynorsk) 2024-08-11 19:53:19 +02:00
Excalidraw Bot
dba1ac4ac6 New translations en.json (Thai) 2024-08-11 19:53:18 +02:00
Excalidraw Bot
f30f1e9eff New translations en.json (Marathi) 2024-08-11 19:53:17 +02:00
Excalidraw Bot
a74bbb0549 New translations en.json (Bengali) 2024-08-11 19:53:16 +02:00
Excalidraw Bot
b5cc1b4ee0 New translations en.json (Tamil) 2024-08-11 19:53:15 +02:00
Excalidraw Bot
3df2c55850 New translations en.json (Khmer) 2024-08-11 19:53:14 +02:00
Excalidraw Bot
0e0b3c62bb New translations en.json (Indonesian) 2024-08-11 19:53:13 +02:00
Excalidraw Bot
ef9b51b47c New translations en.json (Portuguese, Brazilian) 2024-08-11 19:53:12 +02:00
Excalidraw Bot
972db67e55 New translations en.json (Galician) 2024-08-11 19:53:10 +02:00
Excalidraw Bot
e61102d919 New translations en.json (Vietnamese) 2024-08-11 19:53:09 +02:00
Excalidraw Bot
460ea95712 New translations en.json (Chinese Traditional) 2024-08-11 19:53:08 +02:00
Excalidraw Bot
be199f7abb New translations en.json (Chinese Simplified) 2024-08-11 19:53:07 +02:00
Excalidraw Bot
710bffc99c New translations en.json (Ukrainian) 2024-08-11 19:53:06 +02:00
Excalidraw Bot
dec4acdf27 New translations en.json (Turkish) 2024-08-11 19:53:05 +02:00
Excalidraw Bot
dfd70691a9 New translations en.json (Swedish) 2024-08-11 19:53:04 +02:00
Excalidraw Bot
50f7c9d484 New translations en.json (Slovenian) 2024-08-11 19:53:03 +02:00
Excalidraw Bot
f755b09d0d New translations en.json (Slovak) 2024-08-11 19:53:02 +02:00
Excalidraw Bot
70db9f695d New translations en.json (Russian) 2024-08-11 19:53:01 +02:00
Excalidraw Bot
7523ef5869 New translations en.json (Portuguese) 2024-08-11 19:53:00 +02:00
Excalidraw Bot
b7bc8e43ff New translations en.json (Punjabi) 2024-08-11 19:52:59 +02:00
Excalidraw Bot
21c4bac6fc New translations en.json (Dutch) 2024-08-11 19:52:58 +02:00
Excalidraw Bot
e90f450bce New translations en.json (Lithuanian) 2024-08-11 19:52:57 +02:00
Excalidraw Bot
816d3b4b9f New translations en.json (Kurdish) 2024-08-11 19:52:56 +02:00
Excalidraw Bot
9c41187f82 New translations en.json (Korean) 2024-08-11 19:52:55 +02:00
Excalidraw Bot
24b3f87fb3 New translations en.json (Japanese) 2024-08-11 19:52:54 +02:00
Excalidraw Bot
acdae07f35 New translations en.json (Italian) 2024-08-11 19:52:53 +02:00
Excalidraw Bot
a8a67eee74 New translations en.json (Hungarian) 2024-08-11 19:52:52 +02:00
Excalidraw Bot
88fe797d83 New translations en.json (Hebrew) 2024-08-11 19:52:51 +02:00
Excalidraw Bot
d832cfdf71 New translations en.json (Finnish) 2024-08-11 19:52:50 +02:00
Excalidraw Bot
4af813173c New translations en.json (Basque) 2024-08-11 19:52:48 +02:00
Excalidraw Bot
ceeef17c00 New translations en.json (German) 2024-08-11 19:52:47 +02:00
Excalidraw Bot
90a609e7fb New translations en.json (Danish) 2024-08-11 19:52:46 +02:00
Excalidraw Bot
4091d1ef45 New translations en.json (Czech) 2024-08-11 19:52:45 +02:00
Excalidraw Bot
8bfbb60161 New translations en.json (Catalan) 2024-08-11 19:52:44 +02:00
Excalidraw Bot
cea8eb7c35 New translations en.json (Bulgarian) 2024-08-11 19:52:43 +02:00
Excalidraw Bot
339904c990 New translations en.json (Arabic) 2024-08-11 19:52:42 +02:00
Excalidraw Bot
05a087a83d New translations en.json (Spanish) 2024-08-11 19:52:41 +02:00
Excalidraw Bot
c82509b5d2 New translations en.json (French) 2024-08-11 19:52:41 +02:00
Excalidraw Bot
b8ba1918c9 New translations en.json (Romanian) 2024-08-11 19:52:40 +02:00
Excalidraw Bot
f12bf79694 New translations en.json (Greek) 2024-08-11 19:52:38 +02:00
Excalidraw Bot
0b276a371e New translations en.json (Polish) 2024-08-11 19:52:37 +02:00
Excalidraw Bot
0902c97806 New translations en.json (German, Switzerland) 2024-08-11 19:52:36 +02:00
Excalidraw Bot
32d460878d New translations en.json (Persian) 2024-08-11 19:52:35 +02:00
Excalidraw Bot
9a379fb81c New translations en.json (Slovak) 2024-08-11 09:14:17 +02:00
Excalidraw Bot
2f207b561a New translations en.json (Slovak) 2024-08-11 07:50:50 +02:00
Excalidraw Bot
14304f8402 New translations en.json (Romanian) 2024-08-10 18:30:16 +02:00
Excalidraw Bot
d9421730a4 New translations en.json (German) 2024-08-09 20:49:39 +02:00
Excalidraw Bot
fe71ee55c6 New translations en.json (Chinese Traditional) 2024-08-09 09:10:20 +02:00
Excalidraw Bot
8b9cfc82ea New translations en.json (Chinese Traditional) 2024-08-09 07:50:42 +02:00
Excalidraw Bot
2384ac65c3 New translations en.json (Karakalpak) 2024-08-08 23:39:51 +02:00
Excalidraw Bot
71d487762e New translations en.json (Kabyle) 2024-08-08 23:39:49 +02:00
Excalidraw Bot
089136d6e6 New translations en.json (Bengali, India) 2024-08-08 23:39:48 +02:00
Excalidraw Bot
f9955e079e New translations en.json (Occitan) 2024-08-08 23:39:47 +02:00
Excalidraw Bot
1471f87845 New translations en.json (Norwegian Bokmal) 2024-08-08 23:39:46 +02:00
Excalidraw Bot
9467d53088 New translations en.json (Uzbek) 2024-08-08 23:39:45 +02:00
Excalidraw Bot
20eec11057 New translations en.json (Sinhala) 2024-08-08 23:39:44 +02:00
Excalidraw Bot
49dd1c376f New translations en.json (Chinese Traditional, Hong Kong) 2024-08-08 23:39:43 +02:00
Excalidraw Bot
47b4cc67fc New translations en.json (Burmese) 2024-08-08 23:39:42 +02:00
Excalidraw Bot
b4707a1f9f New translations en.json (Hindi) 2024-08-08 23:39:41 +02:00
Excalidraw Bot
c79060a5a4 New translations en.json (Azerbaijani) 2024-08-08 23:39:40 +02:00
Excalidraw Bot
3881f18b01 New translations en.json (Latvian) 2024-08-08 23:39:38 +02:00
Excalidraw Bot
a0d5fbac19 New translations en.json (Kazakh) 2024-08-08 23:39:37 +02:00
Excalidraw Bot
56cb6e7b4f New translations en.json (Norwegian Nynorsk) 2024-08-08 23:39:36 +02:00
Excalidraw Bot
2cc02f02b1 New translations en.json (Thai) 2024-08-08 23:39:35 +02:00
Excalidraw Bot
8f790a65a6 New translations en.json (Marathi) 2024-08-08 23:39:34 +02:00
Excalidraw Bot
fcd7f8daf4 New translations en.json (Bengali) 2024-08-08 23:39:33 +02:00
Excalidraw Bot
6db4b713eb New translations en.json (Tamil) 2024-08-08 23:39:32 +02:00
Excalidraw Bot
f902a93ea1 New translations en.json (Khmer) 2024-08-08 23:39:31 +02:00
Excalidraw Bot
a5e07e633d New translations en.json (Indonesian) 2024-08-08 23:39:30 +02:00
Excalidraw Bot
484a10779b New translations en.json (Portuguese, Brazilian) 2024-08-08 23:39:29 +02:00
Excalidraw Bot
62a9a97323 New translations en.json (Galician) 2024-08-08 23:39:28 +02:00
Excalidraw Bot
37d581abb7 New translations en.json (Vietnamese) 2024-08-08 23:39:27 +02:00
Excalidraw Bot
036f973fa2 New translations en.json (Chinese Traditional) 2024-08-08 23:39:26 +02:00
Excalidraw Bot
f4eeb8038e New translations en.json (Chinese Simplified) 2024-08-08 23:39:24 +02:00
Excalidraw Bot
a29c8365d9 New translations en.json (Ukrainian) 2024-08-08 23:39:23 +02:00
Excalidraw Bot
5d420f54a7 New translations en.json (Turkish) 2024-08-08 23:39:22 +02:00
Excalidraw Bot
35f4ab615f New translations en.json (Swedish) 2024-08-08 23:39:21 +02:00
Excalidraw Bot
043eadf13c New translations en.json (Slovenian) 2024-08-08 23:39:20 +02:00
Excalidraw Bot
a24077c0be New translations en.json (Slovak) 2024-08-08 23:39:19 +02:00
Excalidraw Bot
f958c99a84 New translations en.json (Russian) 2024-08-08 23:39:18 +02:00
Excalidraw Bot
cca43eee02 New translations en.json (Portuguese) 2024-08-08 23:39:17 +02:00
Excalidraw Bot
0d6e9c9537 New translations en.json (Punjabi) 2024-08-08 23:39:16 +02:00
Excalidraw Bot
9c94ea1544 New translations en.json (Dutch) 2024-08-08 23:39:15 +02:00
Excalidraw Bot
fb6804fbd3 New translations en.json (Lithuanian) 2024-08-08 23:39:13 +02:00
Excalidraw Bot
68c6247272 New translations en.json (Kurdish) 2024-08-08 23:39:12 +02:00
Excalidraw Bot
18042a880d New translations en.json (Korean) 2024-08-08 23:39:11 +02:00
Excalidraw Bot
ac06d58d48 New translations en.json (Japanese) 2024-08-08 23:39:10 +02:00
Excalidraw Bot
05d462a07d New translations en.json (Italian) 2024-08-08 23:39:09 +02:00
Excalidraw Bot
ab26013d32 New translations en.json (Hungarian) 2024-08-08 23:39:08 +02:00
Excalidraw Bot
2dcb0ccc1a New translations en.json (Hebrew) 2024-08-08 23:39:07 +02:00
Excalidraw Bot
73f5f9ce9b New translations en.json (Finnish) 2024-08-08 23:39:06 +02:00
Excalidraw Bot
b4fcde00d1 New translations en.json (Basque) 2024-08-08 23:39:05 +02:00
Excalidraw Bot
9d1a01d56d New translations en.json (German) 2024-08-08 23:39:04 +02:00
Excalidraw Bot
f6375b77d5 New translations en.json (Danish) 2024-08-08 23:39:02 +02:00
Excalidraw Bot
ff1c9b3405 New translations en.json (Czech) 2024-08-08 23:39:01 +02:00
Excalidraw Bot
9465e45c97 New translations en.json (Catalan) 2024-08-08 23:39:00 +02:00
Excalidraw Bot
a573fe6b71 New translations en.json (Bulgarian) 2024-08-08 23:38:59 +02:00
Excalidraw Bot
98655e64d5 New translations en.json (Arabic) 2024-08-08 23:38:58 +02:00
Excalidraw Bot
d35214c11b New translations en.json (Spanish) 2024-08-08 23:38:57 +02:00
Excalidraw Bot
2f813d00ed New translations en.json (French) 2024-08-08 23:38:56 +02:00
Excalidraw Bot
580724793b New translations en.json (Romanian) 2024-08-08 23:38:55 +02:00
Excalidraw Bot
fcb9b36b96 New translations en.json (Greek) 2024-08-08 23:38:54 +02:00
Excalidraw Bot
18e37b3abf New translations en.json (Polish) 2024-08-08 23:38:53 +02:00
Excalidraw Bot
379977edbe New translations en.json (German, Switzerland) 2024-08-08 23:38:52 +02:00
Excalidraw Bot
bf061edb78 New translations en.json (Persian) 2024-08-08 23:38:51 +02:00
Excalidraw Bot
616f84bc22 New translations en.json (Romanian) 2024-08-05 08:20:26 +02:00
Excalidraw Bot
a16be8b5c5 New translations en.json (Chinese Traditional) 2024-08-04 18:10:36 +02:00
Excalidraw Bot
296e50678a New translations en.json (Chinese Traditional) 2024-08-04 16:52:27 +02:00
Excalidraw Bot
a6bfa82517 New translations en.json (Hindi) 2024-08-03 17:31:40 +02:00
Excalidraw Bot
050ba515d6 New translations en.json (Marathi) 2024-08-03 17:31:39 +02:00
Excalidraw Bot
d5f559803f New translations en.json (German) 2024-08-02 19:51:09 +02:00
Excalidraw Bot
d0e64458ad New translations en.json (Swedish) 2024-08-02 11:43:46 +02:00
Excalidraw Bot
7715aa6360 New translations en.json (Catalan) 2024-08-02 11:43:45 +02:00
Excalidraw Bot
12e196efee New translations en.json (Chinese Simplified) 2024-08-02 01:53:35 +02:00
Excalidraw Bot
bae2574225 New translations en.json (Russian) 2024-08-01 23:14:35 +02:00
Excalidraw Bot
3137d222ad New translations en.json (Greek) 2024-08-01 23:14:34 +02:00
Excalidraw Bot
4dd0273105 New translations en.json (Slovenian) 2024-08-01 21:17:21 +02:00
Excalidraw Bot
b52ed3425f New translations en.json (Karakalpak) 2024-08-01 20:17:19 +02:00
Excalidraw Bot
9ed6b2576d New translations en.json (Kabyle) 2024-08-01 20:17:18 +02:00
Excalidraw Bot
c5d0401fe1 New translations en.json (Bengali, India) 2024-08-01 20:17:17 +02:00
Excalidraw Bot
da352d54e3 New translations en.json (Occitan) 2024-08-01 20:17:16 +02:00
Excalidraw Bot
40acfd5a25 New translations en.json (Norwegian Bokmal) 2024-08-01 20:17:15 +02:00
Excalidraw Bot
469ab67b2b New translations en.json (Uzbek) 2024-08-01 20:17:13 +02:00
Excalidraw Bot
94c8ca8ced New translations en.json (Sinhala) 2024-08-01 20:17:12 +02:00
Excalidraw Bot
096d6cdb80 New translations en.json (Chinese Traditional, Hong Kong) 2024-08-01 20:17:11 +02:00
Excalidraw Bot
a35abe3398 New translations en.json (Burmese) 2024-08-01 20:17:10 +02:00
Excalidraw Bot
d987d60c14 New translations en.json (Hindi) 2024-08-01 20:17:09 +02:00
Excalidraw Bot
04c2778906 New translations en.json (Azerbaijani) 2024-08-01 20:17:07 +02:00
Excalidraw Bot
e823664f11 New translations en.json (Latvian) 2024-08-01 20:17:06 +02:00
Excalidraw Bot
e09532fd6d New translations en.json (Kazakh) 2024-08-01 20:17:05 +02:00
Excalidraw Bot
26126fd2a5 New translations en.json (Norwegian Nynorsk) 2024-08-01 20:17:04 +02:00
Excalidraw Bot
e8bdb88744 New translations en.json (Thai) 2024-08-01 20:17:02 +02:00
Excalidraw Bot
b91cebbe52 New translations en.json (Marathi) 2024-08-01 20:17:01 +02:00
Excalidraw Bot
90082d3c0d New translations en.json (Bengali) 2024-08-01 20:17:00 +02:00
Excalidraw Bot
de6f6e26c2 New translations en.json (Tamil) 2024-08-01 20:16:59 +02:00
Excalidraw Bot
8ae8cab963 New translations en.json (Khmer) 2024-08-01 20:16:57 +02:00
Excalidraw Bot
436fe171ca New translations en.json (Indonesian) 2024-08-01 20:16:56 +02:00
Excalidraw Bot
0f7f5e0f15 New translations en.json (Portuguese, Brazilian) 2024-08-01 20:16:55 +02:00
Excalidraw Bot
3da680ad39 New translations en.json (Galician) 2024-08-01 20:16:54 +02:00
Excalidraw Bot
91d688d60d New translations en.json (Vietnamese) 2024-08-01 20:16:52 +02:00
Excalidraw Bot
eea678f3c2 New translations en.json (Chinese Traditional) 2024-08-01 20:16:51 +02:00
Excalidraw Bot
87ddb85ce7 New translations en.json (German, Switzerland) 2024-08-01 20:16:50 +02:00
Excalidraw Bot
01619e0dba New translations en.json (Persian) 2024-08-01 20:16:49 +02:00
Excalidraw Bot
63289b016b New translations en.json (Chinese Simplified) 2024-08-01 20:16:48 +02:00
Excalidraw Bot
466bfc5808 New translations en.json (Ukrainian) 2024-08-01 20:16:46 +02:00
Excalidraw Bot
8509ad4ea8 New translations en.json (Turkish) 2024-08-01 20:16:45 +02:00
Excalidraw Bot
f607f3ff01 New translations en.json (Swedish) 2024-08-01 20:16:44 +02:00
Excalidraw Bot
ac4942e64a New translations en.json (Slovenian) 2024-08-01 20:16:43 +02:00
Excalidraw Bot
df32b9e73c New translations en.json (Slovak) 2024-08-01 20:16:42 +02:00
Excalidraw Bot
f924b05782 New translations en.json (Russian) 2024-08-01 20:16:40 +02:00
Excalidraw Bot
804e408f0b New translations en.json (Portuguese) 2024-08-01 20:16:39 +02:00
Excalidraw Bot
5cf811f565 New translations en.json (Punjabi) 2024-08-01 20:16:38 +02:00
Excalidraw Bot
b0e307af53 New translations en.json (Dutch) 2024-08-01 20:16:37 +02:00
Excalidraw Bot
2b64bea8b8 New translations en.json (Lithuanian) 2024-08-01 20:16:35 +02:00
Excalidraw Bot
b938a4eeca New translations en.json (Kurdish) 2024-08-01 20:16:34 +02:00
Excalidraw Bot
ce1babba5a New translations en.json (Korean) 2024-08-01 20:16:33 +02:00
Excalidraw Bot
bdedd55a41 New translations en.json (Japanese) 2024-08-01 20:16:32 +02:00
Excalidraw Bot
fefce6a17b New translations en.json (Italian) 2024-08-01 20:16:30 +02:00
Excalidraw Bot
a9f7c54c74 New translations en.json (Hungarian) 2024-08-01 20:16:29 +02:00
Excalidraw Bot
77bb5164ed New translations en.json (Hebrew) 2024-08-01 20:16:28 +02:00
Excalidraw Bot
aa50fcf3e5 New translations en.json (Finnish) 2024-08-01 20:16:26 +02:00
Excalidraw Bot
101616769f New translations en.json (Basque) 2024-08-01 20:16:25 +02:00
Excalidraw Bot
d86fc99a00 New translations en.json (German) 2024-08-01 20:16:24 +02:00
Excalidraw Bot
d2d1155b18 New translations en.json (Danish) 2024-08-01 20:16:23 +02:00
Excalidraw Bot
a96576d1b2 New translations en.json (Czech) 2024-08-01 20:16:22 +02:00
Excalidraw Bot
6d7f05414b New translations en.json (Catalan) 2024-08-01 20:16:21 +02:00
Excalidraw Bot
f23b6e9350 New translations en.json (Bulgarian) 2024-08-01 20:16:19 +02:00
Excalidraw Bot
391db4a941 New translations en.json (Arabic) 2024-08-01 20:16:18 +02:00
Excalidraw Bot
eccb403da1 New translations en.json (Spanish) 2024-08-01 20:16:17 +02:00
Excalidraw Bot
cd567c3d7e New translations en.json (French) 2024-08-01 20:16:16 +02:00
Excalidraw Bot
570d5c3f15 New translations en.json (Romanian) 2024-08-01 20:16:14 +02:00
Excalidraw Bot
f5a6dffa0b New translations en.json (Greek) 2024-08-01 20:16:13 +02:00
Excalidraw Bot
7507dad1de New translations en.json (Polish) 2024-08-01 20:16:12 +02:00
Excalidraw Bot
844b52eff6 New translations en.json (Russian) 2024-08-01 12:06:17 +02:00
Excalidraw Bot
1ce7dedf67 New translations en.json (Slovak) 2024-07-29 08:46:17 +02:00
Excalidraw Bot
47e3460a0b New translations en.json (Greek) 2024-07-27 23:56:49 +02:00
Excalidraw Bot
d8fbc3236e New translations en.json (French) 2024-07-27 22:55:43 +02:00
Excalidraw Bot
fb78fee714 New translations en.json (Greek) 2024-07-27 22:55:42 +02:00
Excalidraw Bot
27b7338fb8 New translations en.json (Greek) 2024-07-27 21:59:59 +02:00
Excalidraw Bot
439319d77b New translations en.json (Ukrainian) 2024-07-27 10:34:54 +02:00
Excalidraw Bot
49baa6e291 New translations en.json (Ukrainian) 2024-07-27 09:31:27 +02:00
Excalidraw Bot
04eac5ed57 New translations en.json (Chinese Traditional) 2024-07-26 13:44:07 +02:00
Excalidraw Bot
3635c88325 New translations en.json (Catalan) 2024-07-26 11:22:23 +02:00
Excalidraw Bot
8b4fdd368a New translations en.json (Romanian) 2024-07-26 08:23:59 +02:00
Excalidraw Bot
70303a9662 New translations en.json (Russian) 2024-07-25 22:12:04 +02:00
Excalidraw Bot
a6b5ee5f91 New translations en.json (German) 2024-07-25 22:12:03 +02:00
Excalidraw Bot
fad2dc5f57 New translations en.json (Slovenian) 2024-07-25 20:32:19 +02:00
Excalidraw Bot
ffb90b6adb New translations en.json (Karakalpak) 2024-07-25 19:06:18 +02:00
Excalidraw Bot
0c63d297bb New translations en.json (Kabyle) 2024-07-25 19:06:17 +02:00
Excalidraw Bot
0066c94a74 New translations en.json (Bengali, India) 2024-07-25 19:06:16 +02:00
Excalidraw Bot
6c995f172c New translations en.json (Occitan) 2024-07-25 19:06:15 +02:00
Excalidraw Bot
0fd575172f New translations en.json (Norwegian Bokmal) 2024-07-25 19:06:14 +02:00
Excalidraw Bot
f84766f497 New translations en.json (Uzbek) 2024-07-25 19:06:13 +02:00
Excalidraw Bot
2795a33335 New translations en.json (Sinhala) 2024-07-25 19:06:12 +02:00
Excalidraw Bot
dc07d39761 New translations en.json (Chinese Traditional, Hong Kong) 2024-07-25 19:06:10 +02:00
Excalidraw Bot
074ece4fa4 New translations en.json (Burmese) 2024-07-25 19:06:09 +02:00
Excalidraw Bot
affa10abe8 New translations en.json (Hindi) 2024-07-25 19:06:08 +02:00
Excalidraw Bot
68712692fb New translations en.json (Azerbaijani) 2024-07-25 19:06:07 +02:00
Excalidraw Bot
4764f661a3 New translations en.json (Latvian) 2024-07-25 19:06:06 +02:00
Excalidraw Bot
e79d4e8ce6 New translations en.json (Kazakh) 2024-07-25 19:06:05 +02:00
Excalidraw Bot
19ecdea035 New translations en.json (Norwegian Nynorsk) 2024-07-25 19:06:04 +02:00
Excalidraw Bot
0519f6de47 New translations en.json (Thai) 2024-07-25 19:06:02 +02:00
Excalidraw Bot
7407ae0f31 New translations en.json (Marathi) 2024-07-25 19:06:01 +02:00
Excalidraw Bot
887de107ef New translations en.json (Bengali) 2024-07-25 19:06:00 +02:00
Excalidraw Bot
1c471944d1 New translations en.json (Tamil) 2024-07-25 19:05:59 +02:00
Excalidraw Bot
69ee56a228 New translations en.json (Khmer) 2024-07-25 19:05:58 +02:00
Excalidraw Bot
5371082087 New translations en.json (Indonesian) 2024-07-25 19:05:57 +02:00
Excalidraw Bot
2709ccdb56 New translations en.json (Portuguese, Brazilian) 2024-07-25 19:05:56 +02:00
Excalidraw Bot
02361a92dc New translations en.json (Galician) 2024-07-25 19:05:54 +02:00
Excalidraw Bot
175c931ddc New translations en.json (Vietnamese) 2024-07-25 19:05:53 +02:00
Excalidraw Bot
350ba84864 New translations en.json (Chinese Traditional) 2024-07-25 19:05:52 +02:00
Excalidraw Bot
9cca06ac84 New translations en.json (Chinese Simplified) 2024-07-25 19:05:51 +02:00
Excalidraw Bot
5eb4a3a448 New translations en.json (Ukrainian) 2024-07-25 19:05:50 +02:00
Excalidraw Bot
e2a9974791 New translations en.json (Turkish) 2024-07-25 19:05:49 +02:00
Excalidraw Bot
40322d37b6 New translations en.json (Swedish) 2024-07-25 19:05:48 +02:00
Excalidraw Bot
e42426655d New translations en.json (Slovenian) 2024-07-25 19:05:47 +02:00
Excalidraw Bot
d6b0990e2d New translations en.json (Slovak) 2024-07-25 19:05:46 +02:00
Excalidraw Bot
54c1909b9e New translations en.json (Russian) 2024-07-25 19:05:45 +02:00
Excalidraw Bot
7c8daea65b New translations en.json (Portuguese) 2024-07-25 19:05:43 +02:00
Excalidraw Bot
9b6ba7ada6 New translations en.json (Punjabi) 2024-07-25 19:05:42 +02:00
Excalidraw Bot
df389c37a4 New translations en.json (Dutch) 2024-07-25 19:05:41 +02:00
Excalidraw Bot
b616db2ab5 New translations en.json (Lithuanian) 2024-07-25 19:05:40 +02:00
Excalidraw Bot
c43d16f435 New translations en.json (Kurdish) 2024-07-25 19:05:39 +02:00
Excalidraw Bot
9d9c65dcbd New translations en.json (Korean) 2024-07-25 19:05:38 +02:00
Excalidraw Bot
3b01f2cfd4 New translations en.json (Japanese) 2024-07-25 19:05:37 +02:00
Excalidraw Bot
e29d4cbbdc New translations en.json (Italian) 2024-07-25 19:05:36 +02:00
Excalidraw Bot
de73b0df95 New translations en.json (Hungarian) 2024-07-25 19:05:34 +02:00
Excalidraw Bot
bdca46fb3f New translations en.json (Hebrew) 2024-07-25 19:05:33 +02:00
Excalidraw Bot
89e7e0507f New translations en.json (Finnish) 2024-07-25 19:05:32 +02:00
Excalidraw Bot
1092769eaf New translations en.json (Basque) 2024-07-25 19:05:31 +02:00
Excalidraw Bot
76c95fadd9 New translations en.json (German) 2024-07-25 19:05:30 +02:00
Excalidraw Bot
40a945c5c6 New translations en.json (Danish) 2024-07-25 19:05:29 +02:00
Excalidraw Bot
fc029f1581 New translations en.json (Czech) 2024-07-25 19:05:28 +02:00
Excalidraw Bot
160e8c6f08 New translations en.json (Catalan) 2024-07-25 19:05:27 +02:00
Excalidraw Bot
52ac6020dc New translations en.json (Bulgarian) 2024-07-25 19:05:26 +02:00
Excalidraw Bot
966404b2fb New translations en.json (Arabic) 2024-07-25 19:05:25 +02:00
Excalidraw Bot
d151c8be9c New translations en.json (Spanish) 2024-07-25 19:05:24 +02:00
Excalidraw Bot
bf2852b46b New translations en.json (French) 2024-07-25 19:05:23 +02:00
Excalidraw Bot
8d9710795b New translations en.json (Romanian) 2024-07-25 19:05:22 +02:00
Excalidraw Bot
a706856b2a New translations en.json (Greek) 2024-07-25 19:05:21 +02:00
Excalidraw Bot
5362326d91 New translations en.json (Polish) 2024-07-25 19:05:20 +02:00
Excalidraw Bot
a450687669 New translations en.json (German, Switzerland) 2024-07-25 19:05:18 +02:00
Excalidraw Bot
ca31245625 New translations en.json (Persian) 2024-07-25 19:05:17 +02:00
Excalidraw Bot
ea14136124 New translations en.json (Greek) 2024-07-22 22:45:54 +02:00
Excalidraw Bot
69f0b70f65 New translations en.json (Greek) 2024-07-22 21:35:33 +02:00
Excalidraw Bot
6998bef4a5 New translations en.json (Polish) 2024-07-21 22:15:48 +02:00
Excalidraw Bot
ffbeee5e5e New translations en.json (Polish) 2024-07-21 21:09:52 +02:00
Excalidraw Bot
55a203a413 New translations en.json (German, Switzerland) 2024-07-12 10:20:12 +02:00
Excalidraw Bot
d6e91d4cdb New translations en.json (Persian) 2024-07-12 10:20:11 +02:00
Excalidraw Bot
b70bc98b4b New translations en.json (Slovak) 2024-07-06 13:31:55 +02:00
Excalidraw Bot
aaf30dc34e New translations en.json (Slovak) 2024-07-06 11:51:10 +02:00
Excalidraw Bot
d44e0071f0 New translations en.json (Bulgarian) 2024-07-05 12:26:22 +02:00
Excalidraw Bot
790f1a65dc New translations en.json (Bulgarian) 2024-07-05 10:24:50 +02:00
Excalidraw Bot
f7e809c756 New translations en.json (Turkish) 2024-06-29 05:14:14 +02:00
Excalidraw Bot
4ee7585115 New translations en.json (Turkish) 2024-06-29 04:12:41 +02:00
Excalidraw Bot
5a7dd4da43 New translations en.json (Hindi) 2024-06-24 08:46:30 +02:00
Excalidraw Bot
176030fe23 New translations en.json (Marathi) 2024-06-24 08:46:28 +02:00
Excalidraw Bot
ecd17e23b8 New translations en.json (Azerbaijani) 2024-06-18 09:10:44 +02:00
Excalidraw Bot
26df1db785 New translations en.json (Italian) 2024-06-18 09:10:43 +02:00
Excalidraw Bot
5666a0d027 New translations en.json (Azerbaijani) 2024-06-18 07:50:05 +02:00
Excalidraw Bot
43956387b6 Auto commit: Calculate translation coverage 2024-06-17 08:17:41 +00:00
Excalidraw Bot
a6c594a4fa New translations en.json (Hindi) 2024-06-17 10:17:25 +02:00
Excalidraw Bot
733c5881b0 New translations en.json (Marathi) 2024-06-17 10:17:24 +02:00
Excalidraw Bot
6017f5b5a3 Auto commit: Calculate translation coverage 2024-06-17 06:34:30 +00:00
Excalidraw Bot
db4c6f8901 New translations en.json (Marathi) 2024-06-17 08:34:15 +02:00
Excalidraw Bot
73d17e6c08 Auto commit: Calculate translation coverage 2024-06-15 20:24:58 +00:00
Excalidraw Bot
8bc520f05f New translations en.json (French) 2024-06-15 22:24:47 +02:00
Excalidraw Bot
8794935ecb Auto commit: Calculate translation coverage 2024-06-15 18:39:29 +00:00
Excalidraw Bot
9ec989fbef New translations en.json (French) 2024-06-15 20:39:15 +02:00
Excalidraw Bot
470fd2e90c Auto commit: Calculate translation coverage 2024-06-15 14:54:20 +00:00
Excalidraw Bot
67d9217c2c New translations en.json (Occitan) 2024-06-15 16:54:06 +02:00
Excalidraw Bot
fc5f238985 Auto commit: Calculate translation coverage 2024-06-14 19:33:56 +00:00
Excalidraw Bot
9442c0c9ed New translations en.json (Portuguese) 2024-06-14 21:33:43 +02:00
Excalidraw Bot
5afbf5a459 Auto commit: Calculate translation coverage 2024-06-13 20:16:52 +00:00
Excalidraw Bot
a8408a5344 New translations en.json (Chinese Traditional) 2024-06-13 22:16:40 +02:00
Excalidraw Bot
ecf5f2a472 Auto commit: Calculate translation coverage 2024-06-13 08:42:20 +00:00
Excalidraw Bot
66a635eea3 New translations en.json (Romanian) 2024-06-13 10:42:07 +02:00
Excalidraw Bot
316c8b85f8 Auto commit: Calculate translation coverage 2024-06-13 07:34:44 +00:00
Excalidraw Bot
7bfb114ca4 New translations en.json (Swedish) 2024-06-13 09:34:32 +02:00
Excalidraw Bot
8eddf43b93 New translations en.json (Slovenian) 2024-06-13 09:34:30 +02:00
Excalidraw Bot
e83a7b7f93 New translations en.json (Russian) 2024-06-13 09:34:29 +02:00
Excalidraw Bot
c370a5bfeb Auto commit: Calculate translation coverage 2024-06-13 05:11:57 +00:00
Excalidraw Bot
0a0edfa77d New translations en.json (Slovenian) 2024-06-13 07:11:44 +02:00
Excalidraw Bot
e49845e097 Auto commit: Calculate translation coverage 2024-06-13 00:39:11 +00:00
Excalidraw Bot
0cef729b9d New translations en.json (Chinese Simplified) 2024-06-13 02:38:57 +02:00
Excalidraw Bot
59f9d60230 Auto commit: Calculate translation coverage 2024-06-12 23:32:44 +00:00
Excalidraw Bot
8c93c24be5 New translations en.json (Spanish) 2024-06-13 01:32:32 +02:00
Excalidraw Bot
c31f1031ba Auto commit: Calculate translation coverage 2024-06-12 21:05:10 +00:00
Excalidraw Bot
033d32f2e9 New translations en.json (Occitan) 2024-06-12 23:04:31 +02:00
Excalidraw Bot
c9723ca98c Auto commit: Calculate translation coverage 2024-06-12 18:50:51 +00:00
Excalidraw Bot
018372206d New translations en.json (Karakalpak) 2024-06-12 20:49:18 +02:00
Excalidraw Bot
f55a873706 New translations en.json (Kabyle) 2024-06-12 20:49:17 +02:00
Excalidraw Bot
666ad7a867 New translations en.json (Bengali, India) 2024-06-12 20:49:16 +02:00
Excalidraw Bot
a032634c31 New translations en.json (Occitan) 2024-06-12 20:49:15 +02:00
Excalidraw Bot
a5c07896c0 New translations en.json (Norwegian Bokmal) 2024-06-12 20:49:13 +02:00
Excalidraw Bot
c169aebe71 New translations en.json (Uzbek) 2024-06-12 20:49:12 +02:00
Excalidraw Bot
24420ca3b0 New translations en.json (Sinhala) 2024-06-12 20:49:11 +02:00
Excalidraw Bot
9ac67ea8df New translations en.json (Chinese Traditional, Hong Kong) 2024-06-12 20:49:10 +02:00
Excalidraw Bot
23d2c69a7c New translations en.json (Burmese) 2024-06-12 20:49:09 +02:00
Excalidraw Bot
06adcc87d2 New translations en.json (Hindi) 2024-06-12 20:49:08 +02:00
Excalidraw Bot
8a0bf98c41 New translations en.json (Azerbaijani) 2024-06-12 20:49:06 +02:00
Excalidraw Bot
e50436e88c New translations en.json (Latvian) 2024-06-12 20:49:05 +02:00
Excalidraw Bot
dc1b99c4fd New translations en.json (Kazakh) 2024-06-12 20:49:04 +02:00
Excalidraw Bot
468c30792a New translations en.json (Norwegian Nynorsk) 2024-06-12 20:49:03 +02:00
Excalidraw Bot
a9d9457f58 New translations en.json (Thai) 2024-06-12 20:49:02 +02:00
Excalidraw Bot
fcc9f611db New translations en.json (Marathi) 2024-06-12 20:49:00 +02:00
Excalidraw Bot
ecdf65e937 New translations en.json (Bengali) 2024-06-12 20:48:59 +02:00
Excalidraw Bot
643c3da142 New translations en.json (Tamil) 2024-06-12 20:48:58 +02:00
Excalidraw Bot
0e7c995af6 New translations en.json (Khmer) 2024-06-12 20:48:57 +02:00
Excalidraw Bot
f1738bda97 New translations en.json (Persian) 2024-06-12 20:48:55 +02:00
Excalidraw Bot
ede64dc114 New translations en.json (Indonesian) 2024-06-12 20:48:54 +02:00
Excalidraw Bot
42938ac5c5 New translations en.json (Portuguese, Brazilian) 2024-06-12 20:48:53 +02:00
Excalidraw Bot
d7125c969f New translations en.json (Galician) 2024-06-12 20:48:52 +02:00
Excalidraw Bot
37535456c3 New translations en.json (Vietnamese) 2024-06-12 20:48:51 +02:00
Excalidraw Bot
afd2efafe4 New translations en.json (Chinese Traditional) 2024-06-12 20:48:50 +02:00
Excalidraw Bot
67e2a97bfb New translations en.json (Chinese Simplified) 2024-06-12 20:48:49 +02:00
Excalidraw Bot
8d4f5174b2 New translations en.json (Ukrainian) 2024-06-12 20:48:47 +02:00
Excalidraw Bot
271466015b New translations en.json (Turkish) 2024-06-12 20:48:46 +02:00
Excalidraw Bot
6b52e63c57 New translations en.json (Swedish) 2024-06-12 20:48:45 +02:00
Excalidraw Bot
dc5f07105f New translations en.json (Slovenian) 2024-06-12 20:48:44 +02:00
Excalidraw Bot
24ea232cdc New translations en.json (Russian) 2024-06-12 20:48:43 +02:00
Excalidraw Bot
49cac6ed74 New translations en.json (Portuguese) 2024-06-12 20:48:41 +02:00
Excalidraw Bot
680b26f069 New translations en.json (Polish) 2024-06-12 20:48:40 +02:00
Excalidraw Bot
cdc2920522 New translations en.json (Punjabi) 2024-06-12 20:48:39 +02:00
Excalidraw Bot
b52ff062f8 New translations en.json (Dutch) 2024-06-12 20:48:38 +02:00
Excalidraw Bot
1aed1d64f5 New translations en.json (Lithuanian) 2024-06-12 20:48:37 +02:00
Excalidraw Bot
971e09ccc2 New translations en.json (Kurdish) 2024-06-12 20:48:35 +02:00
Excalidraw Bot
aed3f16d61 New translations en.json (Korean) 2024-06-12 20:48:34 +02:00
Excalidraw Bot
56a6563bb3 New translations en.json (Japanese) 2024-06-12 20:48:33 +02:00
Excalidraw Bot
18366513e4 New translations en.json (Italian) 2024-06-12 20:48:32 +02:00
Excalidraw Bot
b7c5435de0 New translations en.json (Hungarian) 2024-06-12 20:48:31 +02:00
Excalidraw Bot
778f2fd540 New translations en.json (Hebrew) 2024-06-12 20:48:29 +02:00
Excalidraw Bot
4649bbd853 New translations en.json (Finnish) 2024-06-12 20:48:28 +02:00
Excalidraw Bot
572c1e3bba New translations en.json (Greek) 2024-06-12 20:48:27 +02:00
Excalidraw Bot
772b232f70 New translations en.json (German) 2024-06-12 20:48:26 +02:00
Excalidraw Bot
86ca8872f5 New translations en.json (Danish) 2024-06-12 20:48:24 +02:00
Excalidraw Bot
2e001220c0 New translations en.json (Czech) 2024-06-12 20:48:23 +02:00
Excalidraw Bot
edf1a62d92 New translations en.json (Catalan) 2024-06-12 20:48:22 +02:00
Excalidraw Bot
605d18b9c5 New translations en.json (Bulgarian) 2024-06-12 20:48:21 +02:00
Excalidraw Bot
834b254a4a New translations en.json (Arabic) 2024-06-12 20:48:20 +02:00
Excalidraw Bot
2513479221 New translations en.json (Spanish) 2024-06-12 20:48:19 +02:00
Excalidraw Bot
41bdf1634d New translations en.json (French) 2024-06-12 20:48:18 +02:00
Excalidraw Bot
4ff5f9ece3 New translations en.json (Romanian) 2024-06-12 20:48:17 +02:00
Excalidraw Bot
6d730443c8 New translations en.json (Basque) 2024-06-12 20:48:16 +02:00
Excalidraw Bot
f7d52c580e New translations en.json (Slovak) 2024-06-12 20:48:14 +02:00
Excalidraw Bot
f0bc165b62 Auto commit: Calculate translation coverage 2024-06-07 11:23:03 +00:00
Excalidraw Bot
d6950a5f88 New translations en.json (Basque) 2024-06-07 13:22:49 +02:00
Excalidraw Bot
07c5d52267 Auto commit: Calculate translation coverage 2024-05-31 16:03:00 +00:00
Excalidraw Bot
bac18cb22f New translations en.json (Slovak) 2024-05-31 18:02:47 +02:00
Excalidraw Bot
f7873520c5 Auto commit: Calculate translation coverage 2024-05-22 10:30:48 +00:00
Excalidraw Bot
1acac43403 New translations en.json (Portuguese) 2024-05-22 12:30:36 +02:00
Excalidraw Bot
3b6a48e955 Auto commit: Calculate translation coverage 2024-05-16 13:26:35 +00:00
Excalidraw Bot
ef51ebb020 New translations en.json (Polish) 2024-05-16 15:26:21 +02:00
Excalidraw Bot
05864777df Auto commit: Calculate translation coverage 2024-05-16 07:13:51 +00:00
Excalidraw Bot
c8b2916c4f New translations en.json (Romanian) 2024-05-16 09:13:38 +02:00
Excalidraw Bot
3f05e42578 Auto commit: Calculate translation coverage 2024-05-16 05:31:07 +00:00
Excalidraw Bot
26e046a102 New translations en.json (Swedish) 2024-05-16 07:30:54 +02:00
Excalidraw Bot
3fc76b9927 New translations en.json (Chinese Traditional) 2024-05-16 04:26:34 +02:00
Excalidraw Bot
85c71304ab Auto commit: Calculate translation coverage 2024-05-15 23:33:43 +00:00
Excalidraw Bot
f6ddf56967 New translations en.json (Chinese Simplified) 2024-05-16 01:33:28 +02:00
Excalidraw Bot
9a59a18033 Auto commit: Calculate translation coverage 2024-05-15 18:07:51 +00:00
Excalidraw Bot
f55dc10b1e New translations en.json (German) 2024-05-15 20:07:39 +02:00
Excalidraw Bot
7128c6ed6c Auto commit: Calculate translation coverage 2024-05-15 17:06:58 +00:00
Excalidraw Bot
b80290f1c0 New translations en.json (Slovenian) 2024-05-15 19:06:46 +02:00
Excalidraw Bot
8fb81d2140 Auto commit: Calculate translation coverage 2024-05-15 13:14:17 +00:00
Excalidraw Bot
7a2b187b5f New translations en.json (Karakalpak) 2024-05-15 15:10:41 +02:00
Excalidraw Bot
f1728c7889 New translations en.json (Kabyle) 2024-05-15 15:10:40 +02:00
Excalidraw Bot
97d6c921a1 New translations en.json (Bengali, India) 2024-05-15 15:10:39 +02:00
Excalidraw Bot
e13b82ebe1 New translations en.json (Occitan) 2024-05-15 15:10:37 +02:00
Excalidraw Bot
a72c4959b2 New translations en.json (Norwegian Bokmal) 2024-05-15 15:10:36 +02:00
Excalidraw Bot
739d947ea3 New translations en.json (Uzbek) 2024-05-15 15:10:35 +02:00
Excalidraw Bot
20e8af7298 New translations en.json (Sinhala) 2024-05-15 15:10:34 +02:00
Excalidraw Bot
6064aeea72 New translations en.json (Chinese Traditional, Hong Kong) 2024-05-15 15:10:33 +02:00
Excalidraw Bot
122f8540a0 New translations en.json (Burmese) 2024-05-15 15:10:31 +02:00
Excalidraw Bot
6f0c6ac307 New translations en.json (Hindi) 2024-05-15 15:10:30 +02:00
Excalidraw Bot
bf26f39c8e New translations en.json (Azerbaijani) 2024-05-15 15:10:29 +02:00
Excalidraw Bot
2d71df249f New translations en.json (Latvian) 2024-05-15 15:10:28 +02:00
Excalidraw Bot
2f96c7705e New translations en.json (Kazakh) 2024-05-15 15:10:27 +02:00
Excalidraw Bot
1ea422d4b0 New translations en.json (Norwegian Nynorsk) 2024-05-15 15:10:25 +02:00
Excalidraw Bot
fb519f5210 New translations en.json (Thai) 2024-05-15 15:10:24 +02:00
Excalidraw Bot
5488f8f053 New translations en.json (Marathi) 2024-05-15 15:10:23 +02:00
Excalidraw Bot
3e8297b923 New translations en.json (Bengali) 2024-05-15 15:10:22 +02:00
Excalidraw Bot
324ff7e6f9 New translations en.json (Tamil) 2024-05-15 15:10:21 +02:00
Excalidraw Bot
d5ec2c5036 New translations en.json (Khmer) 2024-05-15 15:10:19 +02:00
Excalidraw Bot
2267d52345 New translations en.json (Persian) 2024-05-15 15:10:18 +02:00
Excalidraw Bot
3adb3c3943 New translations en.json (Indonesian) 2024-05-15 15:10:17 +02:00
Excalidraw Bot
33c7fb9cc3 New translations en.json (Portuguese, Brazilian) 2024-05-15 15:10:16 +02:00
Excalidraw Bot
595d2ca370 New translations en.json (Galician) 2024-05-15 15:10:14 +02:00
Excalidraw Bot
5f588bb474 New translations en.json (Vietnamese) 2024-05-15 15:10:13 +02:00
Excalidraw Bot
96a190538d New translations en.json (Chinese Traditional) 2024-05-15 15:10:12 +02:00
Excalidraw Bot
2237e6be7b New translations en.json (Chinese Simplified) 2024-05-15 15:10:11 +02:00
Excalidraw Bot
6405585cf6 New translations en.json (Ukrainian) 2024-05-15 15:10:10 +02:00
Excalidraw Bot
3116bc4298 New translations en.json (Turkish) 2024-05-15 15:10:09 +02:00
Excalidraw Bot
8b7572d70e New translations en.json (Swedish) 2024-05-15 15:10:08 +02:00
Excalidraw Bot
d6b0cce4c9 New translations en.json (Slovenian) 2024-05-15 15:10:06 +02:00
Excalidraw Bot
f881130398 New translations en.json (Slovak) 2024-05-15 15:10:05 +02:00
Excalidraw Bot
266c4626be New translations en.json (Russian) 2024-05-15 15:10:03 +02:00
Excalidraw Bot
38290a4887 New translations en.json (Portuguese) 2024-05-15 15:10:02 +02:00
Excalidraw Bot
40b10faa7b New translations en.json (Polish) 2024-05-15 15:10:00 +02:00
Excalidraw Bot
a17a122951 New translations en.json (Punjabi) 2024-05-15 15:09:59 +02:00
Excalidraw Bot
0285684c9e New translations en.json (Dutch) 2024-05-15 15:09:58 +02:00
Excalidraw Bot
20c664d9aa New translations en.json (Lithuanian) 2024-05-15 15:09:57 +02:00
Excalidraw Bot
861e9fae97 New translations en.json (Kurdish) 2024-05-15 15:09:56 +02:00
Excalidraw Bot
d86b27e4cd New translations en.json (Korean) 2024-05-15 15:09:55 +02:00
Excalidraw Bot
75f127506e New translations en.json (Japanese) 2024-05-15 15:09:54 +02:00
Excalidraw Bot
4616455ce6 New translations en.json (Italian) 2024-05-15 15:09:53 +02:00
Excalidraw Bot
255e639ea5 New translations en.json (Hungarian) 2024-05-15 15:09:51 +02:00
Excalidraw Bot
1cb1325ee6 New translations en.json (Finnish) 2024-05-15 15:09:50 +02:00
Excalidraw Bot
ebe229c8ed New translations en.json (Basque) 2024-05-15 15:09:49 +02:00
Excalidraw Bot
63f972a889 New translations en.json (Greek) 2024-05-15 15:09:48 +02:00
Excalidraw Bot
e8e03145a3 New translations en.json (German) 2024-05-15 15:09:47 +02:00
Excalidraw Bot
d2db5fb4ed New translations en.json (Danish) 2024-05-15 15:09:46 +02:00
Excalidraw Bot
b9627e639e New translations en.json (Czech) 2024-05-15 15:09:45 +02:00
Excalidraw Bot
9f9678337e New translations en.json (Catalan) 2024-05-15 15:09:44 +02:00
Excalidraw Bot
ba5dc117a4 New translations en.json (Bulgarian) 2024-05-15 15:09:43 +02:00
Excalidraw Bot
a587e9ab58 New translations en.json (Arabic) 2024-05-15 15:09:42 +02:00
Excalidraw Bot
f93f3732f3 New translations en.json (Spanish) 2024-05-15 15:09:40 +02:00
Excalidraw Bot
128bc579ce New translations en.json (French) 2024-05-15 15:09:39 +02:00
Excalidraw Bot
0dd000ce7e New translations en.json (Romanian) 2024-05-15 15:09:38 +02:00
Excalidraw Bot
926d9e6884 New translations en.json (Hebrew) 2024-05-15 15:09:37 +02:00
Excalidraw Bot
04c46eb668 Auto commit: Calculate translation coverage 2024-05-13 06:43:28 +00:00
Excalidraw Bot
7e09d00d62 New translations en.json (Swedish) 2024-05-13 08:43:12 +02:00
Excalidraw Bot
7ef2a08dff Auto commit: Calculate translation coverage 2024-05-10 14:59:37 +00:00
Excalidraw Bot
ca6d0bb98a New translations en.json (Spanish) 2024-05-10 16:59:25 +02:00
Excalidraw Bot
b70393f947 Auto commit: Calculate translation coverage 2024-05-10 10:46:37 +00:00
Excalidraw Bot
df78472681 New translations en.json (French) 2024-05-10 12:46:26 +02:00
Excalidraw Bot
22d201d2c3 New translations en.json (Romanian) 2024-05-10 12:46:25 +02:00
Excalidraw Bot
3263596166 Auto commit: Calculate translation coverage 2024-05-10 09:07:24 +00:00
Excalidraw Bot
43302acd47 New translations en.json (French) 2024-05-10 11:07:14 +02:00
Excalidraw Bot
c92fb897b0 Auto commit: Calculate translation coverage 2024-05-09 21:37:35 +00:00
Excalidraw Bot
969cdb6fa5 New translations en.json (Portuguese) 2024-05-09 23:37:22 +02:00
Excalidraw Bot
b7c273dad3 New translations en.json (Italian) 2024-05-09 19:35:41 +02:00
Excalidraw Bot
6c392443fc New translations en.json (Chinese Traditional) 2024-05-09 16:06:43 +02:00
Excalidraw Bot
71800f2bdf Auto commit: Calculate translation coverage 2024-05-09 09:15:50 +00:00
Excalidraw Bot
81718fb708 New translations en.json (Chinese Simplified) 2024-05-09 11:15:37 +02:00
Excalidraw Bot
6420601d00 New translations en.json (Russian) 2024-05-09 11:15:36 +02:00
Excalidraw Bot
1ba7399adc New translations en.json (Polish) 2024-05-09 11:15:35 +02:00
Excalidraw Bot
2eacd8be18 New translations en.json (German) 2024-05-09 11:15:34 +02:00
Excalidraw Bot
f9055ae50e Auto commit: Calculate translation coverage 2024-05-09 07:35:38 +00:00
Excalidraw Bot
26718821c0 New translations en.json (Polish) 2024-05-09 09:35:22 +02:00
Excalidraw Bot
0339872a2c Auto commit: Calculate translation coverage 2024-05-09 06:31:00 +00:00
Excalidraw Bot
86758895fa New translations en.json (Slovenian) 2024-05-09 08:30:42 +02:00
Excalidraw Bot
6390aef437 Auto commit: Calculate translation coverage 2024-05-08 20:51:00 +00:00
Excalidraw Bot
f782ee3f0e New translations en.json (Karakalpak) 2024-05-08 22:46:17 +02:00
Excalidraw Bot
971b46bb0d New translations en.json (Kabyle) 2024-05-08 22:46:16 +02:00
Excalidraw Bot
cdda24b859 New translations en.json (Bengali, India) 2024-05-08 22:46:15 +02:00
Excalidraw Bot
bdcbdad7ed New translations en.json (Occitan) 2024-05-08 22:46:14 +02:00
Excalidraw Bot
ae955d24fa New translations en.json (Norwegian Bokmal) 2024-05-08 22:46:13 +02:00
Excalidraw Bot
1787fd8612 New translations en.json (Uzbek) 2024-05-08 22:46:12 +02:00
Excalidraw Bot
ea8e86e4a9 New translations en.json (Sinhala) 2024-05-08 22:46:11 +02:00
Excalidraw Bot
2965f7ba26 New translations en.json (Chinese Traditional, Hong Kong) 2024-05-08 22:46:10 +02:00
Excalidraw Bot
f5e156d0d3 New translations en.json (Burmese) 2024-05-08 22:46:09 +02:00
Excalidraw Bot
e14bb1fa3d New translations en.json (Hindi) 2024-05-08 22:46:07 +02:00
Excalidraw Bot
3d8b49f913 New translations en.json (Azerbaijani) 2024-05-08 22:46:06 +02:00
Excalidraw Bot
3e58bebc04 New translations en.json (Latvian) 2024-05-08 22:46:05 +02:00
Excalidraw Bot
69b7e9c80d New translations en.json (Kazakh) 2024-05-08 22:46:04 +02:00
Excalidraw Bot
812d27cc7f New translations en.json (Norwegian Nynorsk) 2024-05-08 22:46:03 +02:00
Excalidraw Bot
7d383e8c00 New translations en.json (Thai) 2024-05-08 22:46:02 +02:00
Excalidraw Bot
036c8c0f59 New translations en.json (Marathi) 2024-05-08 22:46:01 +02:00
Excalidraw Bot
c08d7a771c New translations en.json (Bengali) 2024-05-08 22:46:00 +02:00
Excalidraw Bot
3bcced5d69 New translations en.json (Tamil) 2024-05-08 22:45:59 +02:00
Excalidraw Bot
9d5c90b5af New translations en.json (Khmer) 2024-05-08 22:45:58 +02:00
Excalidraw Bot
404f9328b7 New translations en.json (Persian) 2024-05-08 22:45:57 +02:00
Excalidraw Bot
35b16fcd6d New translations en.json (Indonesian) 2024-05-08 22:45:56 +02:00
Excalidraw Bot
0d83490292 New translations en.json (Portuguese, Brazilian) 2024-05-08 22:45:55 +02:00
Excalidraw Bot
3c1c3bbdd7 New translations en.json (Galician) 2024-05-08 22:45:54 +02:00
Excalidraw Bot
cc6e945a04 New translations en.json (Vietnamese) 2024-05-08 22:45:53 +02:00
Excalidraw Bot
db6ddf6b7c New translations en.json (Chinese Traditional) 2024-05-08 22:45:52 +02:00
Excalidraw Bot
faca670156 New translations en.json (Chinese Simplified) 2024-05-08 22:45:51 +02:00
Excalidraw Bot
07f39be1ff New translations en.json (Ukrainian) 2024-05-08 22:45:50 +02:00
Excalidraw Bot
5e18fe4c7f New translations en.json (Turkish) 2024-05-08 22:45:49 +02:00
Excalidraw Bot
a8312ec874 New translations en.json (Swedish) 2024-05-08 22:45:48 +02:00
Excalidraw Bot
cef937c880 New translations en.json (Slovenian) 2024-05-08 22:45:46 +02:00
Excalidraw Bot
a8e903a3e9 New translations en.json (Slovak) 2024-05-08 22:45:45 +02:00
Excalidraw Bot
c57c830316 New translations en.json (Russian) 2024-05-08 22:45:44 +02:00
Excalidraw Bot
5b56bfe960 New translations en.json (Portuguese) 2024-05-08 22:45:43 +02:00
Excalidraw Bot
7e3eff3b23 New translations en.json (Polish) 2024-05-08 22:45:42 +02:00
Excalidraw Bot
43f42ee9f0 New translations en.json (Punjabi) 2024-05-08 22:45:41 +02:00
Excalidraw Bot
2674fae183 New translations en.json (Dutch) 2024-05-08 22:45:40 +02:00
Excalidraw Bot
17606e6180 New translations en.json (Lithuanian) 2024-05-08 22:45:39 +02:00
Excalidraw Bot
e5592d566e New translations en.json (Kurdish) 2024-05-08 22:45:38 +02:00
Excalidraw Bot
61768c9d81 New translations en.json (Korean) 2024-05-08 22:45:37 +02:00
Excalidraw Bot
65f4537bd0 New translations en.json (Japanese) 2024-05-08 22:45:36 +02:00
Excalidraw Bot
acd4eda04b New translations en.json (Italian) 2024-05-08 22:45:35 +02:00
Excalidraw Bot
b51369ad97 New translations en.json (Hungarian) 2024-05-08 22:45:34 +02:00
Excalidraw Bot
5b9ec81880 New translations en.json (Finnish) 2024-05-08 22:45:33 +02:00
Excalidraw Bot
91b71c8c45 New translations en.json (Basque) 2024-05-08 22:45:32 +02:00
Excalidraw Bot
cab7c52280 New translations en.json (Greek) 2024-05-08 22:45:31 +02:00
Excalidraw Bot
b1f1ae9570 New translations en.json (German) 2024-05-08 22:45:30 +02:00
Excalidraw Bot
79dec7adc7 New translations en.json (Danish) 2024-05-08 22:45:29 +02:00
Excalidraw Bot
6662cc6828 New translations en.json (Czech) 2024-05-08 22:45:28 +02:00
Excalidraw Bot
8511e6d42c New translations en.json (Catalan) 2024-05-08 22:45:27 +02:00
Excalidraw Bot
aa0c056b2f New translations en.json (Bulgarian) 2024-05-08 22:45:26 +02:00
Excalidraw Bot
bacfe9d327 New translations en.json (Arabic) 2024-05-08 22:45:25 +02:00
Excalidraw Bot
193b40ff12 New translations en.json (Spanish) 2024-05-08 22:45:24 +02:00
Excalidraw Bot
020b88c77a New translations en.json (French) 2024-05-08 22:45:23 +02:00
Excalidraw Bot
77726e6606 New translations en.json (Romanian) 2024-05-08 22:45:22 +02:00
Excalidraw Bot
1f055c0bda New translations en.json (Hebrew) 2024-05-08 22:45:21 +02:00
Excalidraw Bot
0189a75ff3 Auto commit: Calculate translation coverage 2024-05-08 19:33:58 +00:00
Excalidraw Bot
60d55753e9 New translations en.json (Portuguese) 2024-05-08 21:33:46 +02:00
Excalidraw Bot
c962575aec Auto commit: Calculate translation coverage 2024-05-08 10:49:45 +00:00
Excalidraw Bot
50da3e0873 New translations en.json (Romanian) 2024-05-08 12:49:33 +02:00
Excalidraw Bot
8b7a5511b7 Auto commit: Calculate translation coverage 2024-05-08 05:01:04 +00:00
Excalidraw Bot
572185898c New translations en.json (Tamil) 2024-05-08 07:00:51 +02:00
Excalidraw Bot
f6ea289a0e New translations en.json (Chinese Traditional) 2024-05-08 05:50:02 +02:00
Excalidraw Bot
dc9b065689 Auto commit: Calculate translation coverage 2024-05-07 19:33:43 +00:00
Excalidraw Bot
a448dc81c4 New translations en.json (German) 2024-05-07 21:33:32 +02:00
Excalidraw Bot
d82dae0776 Auto commit: Calculate translation coverage 2024-05-07 18:35:50 +00:00
Excalidraw Bot
0447ac624d New translations en.json (Tamil) 2024-05-07 20:35:37 +02:00
Excalidraw Bot
b9c040d9ac New translations en.json (Chinese Simplified) 2024-05-07 20:35:36 +02:00
Excalidraw Bot
fc926448ac New translations en.json (Spanish) 2024-05-07 19:40:01 +02:00
Excalidraw Bot
70d85530c7 Auto commit: Calculate translation coverage 2024-05-07 13:49:47 +00:00
Excalidraw Bot
96b515e2fe New translations en.json (Slovenian) 2024-05-07 15:49:36 +02:00
Excalidraw Bot
bced18876d New translations en.json (Russian) 2024-05-07 15:49:35 +02:00
Excalidraw Bot
1be9d67d8a Auto commit: Calculate translation coverage 2024-05-07 12:32:31 +00:00
Excalidraw Bot
bd21a2b57f New translations en.json (Karakalpak) 2024-05-07 14:30:33 +02:00
Excalidraw Bot
8cd33a127c New translations en.json (Kabyle) 2024-05-07 14:30:32 +02:00
Excalidraw Bot
19f15becfe New translations en.json (Bengali, India) 2024-05-07 14:30:30 +02:00
Excalidraw Bot
4f0e0407f1 New translations en.json (Occitan) 2024-05-07 14:30:29 +02:00
Excalidraw Bot
dc1f76988a New translations en.json (Norwegian Bokmal) 2024-05-07 14:30:28 +02:00
Excalidraw Bot
8289f3e0ed New translations en.json (Uzbek) 2024-05-07 14:30:27 +02:00
Excalidraw Bot
a5f517c0d4 New translations en.json (Sinhala) 2024-05-07 14:30:26 +02:00
Excalidraw Bot
3c2cd278f7 New translations en.json (Chinese Traditional, Hong Kong) 2024-05-07 14:30:24 +02:00
Excalidraw Bot
c77e248aee New translations en.json (Burmese) 2024-05-07 14:30:23 +02:00
Excalidraw Bot
2948341728 New translations en.json (Hindi) 2024-05-07 14:30:22 +02:00
Excalidraw Bot
9eaf570ae7 New translations en.json (Azerbaijani) 2024-05-07 14:30:20 +02:00
Excalidraw Bot
5d3637d157 New translations en.json (Latvian) 2024-05-07 14:30:19 +02:00
Excalidraw Bot
955af18a01 New translations en.json (Kazakh) 2024-05-07 14:30:18 +02:00
Excalidraw Bot
77d8fd5493 New translations en.json (Norwegian Nynorsk) 2024-05-07 14:30:17 +02:00
Excalidraw Bot
40e6f4a7f2 New translations en.json (Thai) 2024-05-07 14:30:16 +02:00
Excalidraw Bot
640d838e28 New translations en.json (Marathi) 2024-05-07 14:30:15 +02:00
Excalidraw Bot
aa02c7610e New translations en.json (Bengali) 2024-05-07 14:30:13 +02:00
Excalidraw Bot
d1179f5ada New translations en.json (Tamil) 2024-05-07 14:30:12 +02:00
Excalidraw Bot
6df2d19fbf New translations en.json (Khmer) 2024-05-07 14:30:11 +02:00
Excalidraw Bot
52ba265c71 New translations en.json (Persian) 2024-05-07 14:30:10 +02:00
Excalidraw Bot
00d9e244c2 New translations en.json (Indonesian) 2024-05-07 14:30:08 +02:00
Excalidraw Bot
ee0c58f797 New translations en.json (Portuguese, Brazilian) 2024-05-07 14:30:07 +02:00
Excalidraw Bot
2fd1d1c371 New translations en.json (Galician) 2024-05-07 14:30:06 +02:00
Excalidraw Bot
7a51bc7f5d New translations en.json (Vietnamese) 2024-05-07 14:30:05 +02:00
Excalidraw Bot
28b61d73c8 New translations en.json (Chinese Traditional) 2024-05-07 14:30:03 +02:00
Excalidraw Bot
f8af81fb65 New translations en.json (Chinese Simplified) 2024-05-07 14:30:02 +02:00
Excalidraw Bot
d474fdd404 New translations en.json (Ukrainian) 2024-05-07 14:30:00 +02:00
Excalidraw Bot
1afd2d4030 New translations en.json (Turkish) 2024-05-07 14:29:59 +02:00
Excalidraw Bot
94bc8dd018 New translations en.json (Swedish) 2024-05-07 14:29:58 +02:00
Excalidraw Bot
f3e85108a8 New translations en.json (Slovenian) 2024-05-07 14:29:57 +02:00
Excalidraw Bot
149a7fc32b New translations en.json (Slovak) 2024-05-07 14:29:56 +02:00
Excalidraw Bot
7094c4c9b6 New translations en.json (Russian) 2024-05-07 14:29:55 +02:00
Excalidraw Bot
e7fb9494cb New translations en.json (Portuguese) 2024-05-07 14:29:53 +02:00
Excalidraw Bot
b335a96722 New translations en.json (Polish) 2024-05-07 14:29:52 +02:00
Excalidraw Bot
18f539c709 New translations en.json (Punjabi) 2024-05-07 14:29:51 +02:00
Excalidraw Bot
2bd173501c New translations en.json (Dutch) 2024-05-07 14:29:50 +02:00
Excalidraw Bot
27c47513e8 New translations en.json (Lithuanian) 2024-05-07 14:29:49 +02:00
Excalidraw Bot
bafd3d669b New translations en.json (Kurdish) 2024-05-07 14:29:48 +02:00
Excalidraw Bot
d9a3ec2680 New translations en.json (Korean) 2024-05-07 14:29:47 +02:00
Excalidraw Bot
b28f7b9b81 New translations en.json (Japanese) 2024-05-07 14:29:45 +02:00
Excalidraw Bot
f35b909ba9 New translations en.json (Italian) 2024-05-07 14:29:44 +02:00
Excalidraw Bot
dbe71af81a New translations en.json (Hungarian) 2024-05-07 14:29:43 +02:00
Excalidraw Bot
8a94fd0baf New translations en.json (Finnish) 2024-05-07 14:29:42 +02:00
Excalidraw Bot
b9a4bcb4fc New translations en.json (Basque) 2024-05-07 14:29:41 +02:00
Excalidraw Bot
11f6dd674c New translations en.json (Greek) 2024-05-07 14:29:40 +02:00
Excalidraw Bot
edfdf8ad21 New translations en.json (German) 2024-05-07 14:29:39 +02:00
Excalidraw Bot
40a4928f6e New translations en.json (Danish) 2024-05-07 14:29:38 +02:00
Excalidraw Bot
b35257ab5b New translations en.json (Czech) 2024-05-07 14:29:36 +02:00
Excalidraw Bot
4b9f2a722d New translations en.json (Catalan) 2024-05-07 14:29:35 +02:00
Excalidraw Bot
7c88a7c48b New translations en.json (Bulgarian) 2024-05-07 14:29:34 +02:00
Excalidraw Bot
a8adca5d98 New translations en.json (Arabic) 2024-05-07 14:29:33 +02:00
Excalidraw Bot
ee88a62da8 New translations en.json (Spanish) 2024-05-07 14:29:32 +02:00
Excalidraw Bot
acb23a5a7a New translations en.json (French) 2024-05-07 14:29:30 +02:00
Excalidraw Bot
1b63aa136b New translations en.json (Romanian) 2024-05-07 14:29:29 +02:00
Excalidraw Bot
cea3bb9764 New translations en.json (Hebrew) 2024-05-07 14:29:28 +02:00
Excalidraw Bot
1840949a81 Auto commit: Calculate translation coverage 2024-04-23 20:54:02 +00:00
Excalidraw Bot
b6678560ec New translations en.json (Hebrew) 2024-04-23 22:53:48 +02:00
Excalidraw Bot
01c144de36 Auto commit: Calculate translation coverage 2024-04-23 19:31:24 +00:00
Excalidraw Bot
5f387aeed1 New translations en.json (Hebrew) 2024-04-23 21:31:12 +02:00
Excalidraw Bot
1faad458f6 Auto commit: Calculate translation coverage 2024-04-22 15:39:31 +00:00
Excalidraw Bot
3357340772 New translations en.json (Bengali, India) 2024-04-22 17:39:12 +02:00
Excalidraw Bot
053606e460 New translations en.json (Bengali) 2024-04-22 17:39:11 +02:00
Excalidraw Bot
280bbc3e58 Auto commit: Calculate translation coverage 2024-04-22 14:43:54 +00:00
Excalidraw Bot
6adf3eb827 New translations en.json (Bengali) 2024-04-22 16:43:40 +02:00
Excalidraw Bot
2259ea6e80 Auto commit: Calculate translation coverage 2024-04-17 15:16:08 +00:00
Excalidraw Bot
51eec9d02c New translations en.json (Finnish) 2024-04-17 17:15:54 +02:00
Excalidraw Bot
6dcfe61f2e Auto commit: Calculate translation coverage 2024-04-16 11:45:30 +00:00
Excalidraw Bot
066bcddc82 New translations en.json (Portuguese) 2024-04-16 13:45:15 +02:00
Excalidraw Bot
67866e70cf Auto commit: Calculate translation coverage 2024-04-15 13:28:35 +00:00
Excalidraw Bot
3509c2e812 New translations en.json (Arabic) 2024-04-15 15:28:23 +02:00
Excalidraw Bot
4f0ea27632 Auto commit: Calculate translation coverage 2024-04-15 12:14:28 +00:00
Excalidraw Bot
5eb7b5a63e New translations en.json (Arabic) 2024-04-15 14:14:10 +02:00
Excalidraw Bot
865576946c Auto commit: Calculate translation coverage 2024-04-15 10:53:28 +00:00
Excalidraw Bot
5a376e0015 New translations en.json (Romanian) 2024-04-15 12:53:17 +02:00
Excalidraw Bot
d34d43d730 Auto commit: Calculate translation coverage 2024-04-15 05:38:15 +00:00
Excalidraw Bot
f7b4d9d424 New translations en.json (Swedish) 2024-04-15 07:38:04 +02:00
Excalidraw Bot
10b7e96c00 Auto commit: Calculate translation coverage 2024-04-13 21:41:12 +00:00
Excalidraw Bot
a5c09041e9 New translations en.json (Chinese Simplified) 2024-04-13 23:40:59 +02:00
Excalidraw Bot
c46e268ad0 Auto commit: Calculate translation coverage 2024-04-13 20:27:01 +00:00
Excalidraw Bot
5b6ce786a1 New translations en.json (Chinese Traditional) 2024-04-13 22:26:47 +02:00
Excalidraw Bot
70a2ccb51a New translations en.json (German) 2024-04-13 22:26:46 +02:00
Excalidraw Bot
a89a072cb4 Auto commit: Calculate translation coverage 2024-04-13 17:59:17 +00:00
Excalidraw Bot
65c040c075 New translations en.json (Karakalpak) 2024-04-13 19:55:18 +02:00
Excalidraw Bot
39b9e1e7a0 New translations en.json (Kabyle) 2024-04-13 19:55:17 +02:00
Excalidraw Bot
cb3050294b New translations en.json (Occitan) 2024-04-13 19:55:16 +02:00
Excalidraw Bot
455eeb63b4 New translations en.json (Norwegian Bokmal) 2024-04-13 19:55:15 +02:00
Excalidraw Bot
be4eb1e37e New translations en.json (Uzbek) 2024-04-13 19:55:14 +02:00
Excalidraw Bot
f3ff017e6f New translations en.json (Sinhala) 2024-04-13 19:55:13 +02:00
Excalidraw Bot
56c18f44c7 New translations en.json (Chinese Traditional, Hong Kong) 2024-04-13 19:55:12 +02:00
Excalidraw Bot
da2695ac35 New translations en.json (Burmese) 2024-04-13 19:55:11 +02:00
Excalidraw Bot
5614f1c62f New translations en.json (Azerbaijani) 2024-04-13 19:55:09 +02:00
Excalidraw Bot
b7d9e49039 New translations en.json (Latvian) 2024-04-13 19:55:08 +02:00
Excalidraw Bot
4da5b9e7b6 New translations en.json (Kazakh) 2024-04-13 19:55:07 +02:00
Excalidraw Bot
81958d4a3d New translations en.json (Norwegian Nynorsk) 2024-04-13 19:55:06 +02:00
Excalidraw Bot
12a7eb4885 New translations en.json (Thai) 2024-04-13 19:55:05 +02:00
Excalidraw Bot
dffc310969 New translations en.json (Marathi) 2024-04-13 19:55:05 +02:00
Excalidraw Bot
80ad916f4f New translations en.json (Bengali) 2024-04-13 19:55:04 +02:00
Excalidraw Bot
d216420f30 New translations en.json (Tamil) 2024-04-13 19:55:03 +02:00
Excalidraw Bot
4cf68fa98f New translations en.json (Khmer) 2024-04-13 19:55:02 +02:00
Excalidraw Bot
2996eb0bb5 New translations en.json (Persian) 2024-04-13 19:55:01 +02:00
Excalidraw Bot
422e6ad51e New translations en.json (Indonesian) 2024-04-13 19:55:00 +02:00
Excalidraw Bot
922675bf53 New translations en.json (Portuguese, Brazilian) 2024-04-13 19:54:59 +02:00
Excalidraw Bot
d92f555e93 New translations en.json (Galician) 2024-04-13 19:54:58 +02:00
Excalidraw Bot
48433bc9eb New translations en.json (Vietnamese) 2024-04-13 19:54:57 +02:00
Excalidraw Bot
db3f73c643 New translations en.json (Chinese Traditional) 2024-04-13 19:54:57 +02:00
Excalidraw Bot
ad0f8155a7 New translations en.json (Ukrainian) 2024-04-13 19:54:56 +02:00
Excalidraw Bot
060eee3afd New translations en.json (Turkish) 2024-04-13 19:54:55 +02:00
Excalidraw Bot
407ef4699d New translations en.json (Slovenian) 2024-04-13 19:54:54 +02:00
Excalidraw Bot
1ffb358d59 New translations en.json (Russian) 2024-04-13 19:54:53 +02:00
Excalidraw Bot
d9c4e12642 New translations en.json (Portuguese) 2024-04-13 19:54:52 +02:00
Excalidraw Bot
310f561488 New translations en.json (Polish) 2024-04-13 19:54:51 +02:00
Excalidraw Bot
dcd3636c96 New translations en.json (Punjabi) 2024-04-13 19:54:50 +02:00
Excalidraw Bot
a5442f8b7a New translations en.json (Dutch) 2024-04-13 19:54:50 +02:00
Excalidraw Bot
1dc32d9e0a New translations en.json (Lithuanian) 2024-04-13 19:54:49 +02:00
Excalidraw Bot
a767150e87 New translations en.json (Kurdish) 2024-04-13 19:54:48 +02:00
Excalidraw Bot
9691492f38 New translations en.json (Korean) 2024-04-13 19:54:47 +02:00
Excalidraw Bot
2f52f28631 New translations en.json (Japanese) 2024-04-13 19:54:46 +02:00
Excalidraw Bot
e0bef262a7 New translations en.json (Hungarian) 2024-04-13 19:54:45 +02:00
Excalidraw Bot
4cffdf216d New translations en.json (Hebrew) 2024-04-13 19:54:44 +02:00
Excalidraw Bot
2628d6807c New translations en.json (Finnish) 2024-04-13 19:54:43 +02:00
Excalidraw Bot
3e1012b080 New translations en.json (Basque) 2024-04-13 19:54:43 +02:00
Excalidraw Bot
6e575f2f8b New translations en.json (Greek) 2024-04-13 19:54:42 +02:00
Excalidraw Bot
ec7fa95672 New translations en.json (German) 2024-04-13 19:54:41 +02:00
Excalidraw Bot
753f492c86 New translations en.json (Danish) 2024-04-13 19:54:40 +02:00
Excalidraw Bot
8b04af03a1 New translations en.json (Czech) 2024-04-13 19:54:39 +02:00
Excalidraw Bot
8830f1138d New translations en.json (Catalan) 2024-04-13 19:54:38 +02:00
Excalidraw Bot
4567a16d65 New translations en.json (Bulgarian) 2024-04-13 19:54:37 +02:00
Excalidraw Bot
19eaf8240a New translations en.json (Arabic) 2024-04-13 19:54:36 +02:00
Excalidraw Bot
4a519f47b5 New translations en.json (Spanish) 2024-04-13 19:54:35 +02:00
Excalidraw Bot
edebbffe33 New translations en.json (French) 2024-04-13 19:54:34 +02:00
Excalidraw Bot
156285417b New translations en.json (Romanian) 2024-04-13 19:54:33 +02:00
Excalidraw Bot
cefc312e85 New translations en.json (Hindi) 2024-04-13 19:54:32 +02:00
Excalidraw Bot
c63d5da9e1 New translations en.json (Chinese Simplified) 2024-04-13 19:54:31 +02:00
Excalidraw Bot
a934d975e7 New translations en.json (Swedish) 2024-04-13 19:54:30 +02:00
Excalidraw Bot
f391e7b11a New translations en.json (Slovak) 2024-04-13 19:54:29 +02:00
Excalidraw Bot
7f93f19314 New translations en.json (Italian) 2024-04-13 19:54:29 +02:00
dwelle
cb1454f8db Merge branch 'master' into l10n_master 2024-04-13 18:52:39 +02:00
David Luzar
da2e507298 fix: allow same origin for all necessary domains (#7889) 2024-04-13 18:51:30 +02:00
Excalidraw Bot
df4660c0c1 Auto commit: Calculate translation coverage 2024-04-13 12:29:26 +00:00
Excalidraw Bot
8751b38988 New translations en.json (Slovak) 2024-04-13 14:29:12 +02:00
David Luzar
f59b4f6af4 fix: always make sure we render bound text above containers (#7880) 2024-04-12 21:50:02 +02:00
David Luzar
afcde542f9 fix: parse embeddable srcdoc urls strictly (#7884) 2024-04-12 20:51:17 +02:00
Ryan Di
4689a6b300 fix: hit test for closed sharp curves (#7881) 2024-04-12 12:58:51 +02:00
David Luzar
0ae9b383d6 fix: Gist embed allowing unsafe html (#7883) 2024-04-12 12:57:43 +02:00
David Luzar
f597bd3e01 fix: command palette tweaks and fixes (#7876) 2024-04-11 11:39:19 +02:00
Ryan Di
4987cc53d0 fix: include borders when testing insides of a shape (#7865) 2024-04-09 16:07:36 +02:00
Rinku Chaudhari
d917db438e fix: external link not opening (#7859) 2024-04-09 16:06:49 +02:00
Excalidraw Bot
287836fc6b Auto commit: Calculate translation coverage 2024-04-09 08:38:48 +00:00
Excalidraw Bot
4635477f37 New translations en.json (Swedish) 2024-04-09 10:38:34 +02:00
Excalidraw Bot
89f77ea24a Auto commit: Calculate translation coverage 2024-04-09 04:32:41 +00:00
Excalidraw Bot
3dc38ab06e New translations en.json (Chinese Simplified) 2024-04-09 06:32:30 +02:00
Aakansha Doshi
a33a400f01 fix: add safe check for arrow points length in tranformToExcalidrawElements (#7863)
* fix: add safe check for arrow points length in tranformToExcalidrawElements

* add spec

* throw error only for dev mode

* fix lint
2024-04-09 09:56:21 +05:30
Excalidraw Bot
66a2dcdedc Auto commit: Calculate translation coverage 2024-04-09 03:32:30 +00:00
Excalidraw Bot
fddea948f0 New translations en.json (Marathi) 2024-04-09 05:32:14 +02:00
Excalidraw Bot
229ab44918 New translations en.json (Hindi) 2024-04-09 05:32:13 +02:00
Excalidraw Bot
a6a958de55 New translations en.json (Chinese Traditional) 2024-04-08 21:16:08 +02:00
Excalidraw Bot
c3969dcf12 Auto commit: Calculate translation coverage 2024-04-08 18:06:08 +00:00
Excalidraw Bot
d906fe2531 New translations en.json (German) 2024-04-08 20:05:52 +02:00
Excalidraw Bot
3eaa573951 Auto commit: Calculate translation coverage 2024-04-08 16:49:55 +00:00
Excalidraw Bot
50f98d193d New translations en.json (Slovenian) 2024-04-08 18:49:21 +02:00
Excalidraw Bot
7104d7bf17 New translations en.json (Romanian) 2024-04-08 18:49:20 +02:00
David Luzar
8a162a4cb4 fix: import (#7869) 2024-04-08 16:59:03 +02:00
Excalidraw Bot
9403ef8656 Auto commit: Calculate translation coverage 2024-04-08 14:55:38 +00:00
David Luzar
c6a045d092 fix: theme toggle shortcut event.code (#7868) 2024-04-08 16:55:33 +02:00
Excalidraw Bot
092263b6b1 New translations en.json (Karakalpak) 2024-04-08 16:51:11 +02:00
Excalidraw Bot
6adb44ead4 New translations en.json (Kabyle) 2024-04-08 16:51:10 +02:00
Excalidraw Bot
b71cbe8352 New translations en.json (Occitan) 2024-04-08 16:51:09 +02:00
Excalidraw Bot
576cb578b0 New translations en.json (Norwegian Bokmal) 2024-04-08 16:51:08 +02:00
Excalidraw Bot
7198a613dd New translations en.json (Uzbek) 2024-04-08 16:51:07 +02:00
Excalidraw Bot
24d4eafbd0 New translations en.json (Sinhala) 2024-04-08 16:51:06 +02:00
Excalidraw Bot
8b52f043d5 New translations en.json (Chinese Traditional, Hong Kong) 2024-04-08 16:51:05 +02:00
Excalidraw Bot
6e2c5d7e82 New translations en.json (Burmese) 2024-04-08 16:51:04 +02:00
Excalidraw Bot
ae82cf1704 New translations en.json (Azerbaijani) 2024-04-08 16:51:03 +02:00
Excalidraw Bot
1e0f54b4df New translations en.json (Latvian) 2024-04-08 16:51:02 +02:00
Excalidraw Bot
4624dd5041 New translations en.json (Kazakh) 2024-04-08 16:51:01 +02:00
Excalidraw Bot
1e54ae0825 New translations en.json (Norwegian Nynorsk) 2024-04-08 16:50:59 +02:00
Excalidraw Bot
6bfc4b7212 New translations en.json (Thai) 2024-04-08 16:50:58 +02:00
Excalidraw Bot
81634d45e4 New translations en.json (Marathi) 2024-04-08 16:50:57 +02:00
Excalidraw Bot
cd1c9391f1 New translations en.json (Bengali) 2024-04-08 16:50:56 +02:00
Excalidraw Bot
726ccccb1c New translations en.json (Tamil) 2024-04-08 16:50:55 +02:00
Excalidraw Bot
74942af896 New translations en.json (Khmer) 2024-04-08 16:50:54 +02:00
Excalidraw Bot
89e52da2fe New translations en.json (Persian) 2024-04-08 16:50:53 +02:00
Excalidraw Bot
fcf153e420 New translations en.json (Indonesian) 2024-04-08 16:50:52 +02:00
Excalidraw Bot
c22f0896b7 New translations en.json (Portuguese, Brazilian) 2024-04-08 16:50:51 +02:00
Excalidraw Bot
b3bf5a215f New translations en.json (Galician) 2024-04-08 16:50:51 +02:00
Excalidraw Bot
5a0066ab52 New translations en.json (Vietnamese) 2024-04-08 16:50:49 +02:00
Excalidraw Bot
b85c365aa9 New translations en.json (Chinese Traditional) 2024-04-08 16:50:49 +02:00
Excalidraw Bot
7b1eaf3f48 New translations en.json (Ukrainian) 2024-04-08 16:50:48 +02:00
Excalidraw Bot
16cb262a26 New translations en.json (Turkish) 2024-04-08 16:50:46 +02:00
Excalidraw Bot
35e2663504 New translations en.json (Slovenian) 2024-04-08 16:50:44 +02:00
Excalidraw Bot
81aaa909af New translations en.json (Russian) 2024-04-08 16:50:43 +02:00
Excalidraw Bot
976384a0a7 New translations en.json (Portuguese) 2024-04-08 16:50:42 +02:00
Excalidraw Bot
e989f1ff6c New translations en.json (Polish) 2024-04-08 16:50:41 +02:00
Excalidraw Bot
4237138392 New translations en.json (Punjabi) 2024-04-08 16:50:40 +02:00
Excalidraw Bot
192b67ee73 New translations en.json (Dutch) 2024-04-08 16:50:39 +02:00
Excalidraw Bot
7e2c567e33 New translations en.json (Lithuanian) 2024-04-08 16:50:38 +02:00
Excalidraw Bot
0659407aa8 New translations en.json (Kurdish) 2024-04-08 16:50:37 +02:00
Excalidraw Bot
c2f5ac17a7 New translations en.json (Korean) 2024-04-08 16:50:36 +02:00
Excalidraw Bot
ab7c9a4106 New translations en.json (Japanese) 2024-04-08 16:50:35 +02:00
Excalidraw Bot
e9e5671356 New translations en.json (Hungarian) 2024-04-08 16:50:34 +02:00
Excalidraw Bot
f447cbcc9f New translations en.json (Hebrew) 2024-04-08 16:50:33 +02:00
Excalidraw Bot
cea81f15a7 New translations en.json (Finnish) 2024-04-08 16:50:32 +02:00
Excalidraw Bot
bae392ce50 New translations en.json (Basque) 2024-04-08 16:50:31 +02:00
Excalidraw Bot
5eea304b1d New translations en.json (Greek) 2024-04-08 16:50:30 +02:00
Excalidraw Bot
dba82deef4 New translations en.json (German) 2024-04-08 16:50:29 +02:00
Excalidraw Bot
14a64cad6e New translations en.json (Danish) 2024-04-08 16:50:28 +02:00
Excalidraw Bot
bf73490b78 New translations en.json (Czech) 2024-04-08 16:50:27 +02:00
Excalidraw Bot
50462b4956 New translations en.json (Catalan) 2024-04-08 16:50:26 +02:00
Excalidraw Bot
64087e6055 New translations en.json (Bulgarian) 2024-04-08 16:50:25 +02:00
Excalidraw Bot
8933a677c0 New translations en.json (Arabic) 2024-04-08 16:50:24 +02:00
Excalidraw Bot
ac487862e9 New translations en.json (Spanish) 2024-04-08 16:50:23 +02:00
Excalidraw Bot
6202f38f70 New translations en.json (French) 2024-04-08 16:50:22 +02:00
Excalidraw Bot
a4779bfe73 New translations en.json (Romanian) 2024-04-08 16:50:21 +02:00
Excalidraw Bot
40874a88ef New translations en.json (Hindi) 2024-04-08 16:50:20 +02:00
Excalidraw Bot
88f6c86c9e New translations en.json (Chinese Simplified) 2024-04-08 16:50:19 +02:00
Excalidraw Bot
55bc4a6365 New translations en.json (Swedish) 2024-04-08 16:50:18 +02:00
Excalidraw Bot
3fb6ab5e45 New translations en.json (Slovak) 2024-04-08 16:50:17 +02:00
Excalidraw Bot
44d7db20e6 New translations en.json (Italian) 2024-04-08 16:50:16 +02:00
Arnost Pleskot
cd50aa719f feat: add system mode to the theme selector (#7853)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-08 16:46:24 +02:00
David Luzar
92bc08207c fix: remove incorrect check from index.html (#7867) 2024-04-08 16:42:00 +02:00
Excalidraw Bot
8ffed1b059 Auto commit: Calculate translation coverage 2024-04-08 09:51:23 +00:00
Excalidraw Bot
5cae67c1cb New translations en.json (Vietnamese) 2024-04-08 11:51:09 +02:00
Ryan Di
32df5502ae feat: fractional indexing (#7359)
* Introducing fractional indices as part of `element.index`

* Ensuring invalid fractional indices are always synchronized with the array order

* Simplifying reconciliation based on the fractional indices

* Moving reconciliation inside the `@excalidraw/excalidraw` package

---------

Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-04 13:51:11 +01:00
Ryan Di
bbdcd30a73 refactor: update collision from ga to vector geometry (#7636)
* new collision api

* isPointOnShape

* removed redundant code

* new collision methods in app

* curve shape takes starting point

* clean up geometry

* curve rotation

* freedraw

* inside curve

* improve ellipse inside check

* ellipse distance func

* curve inside

* include frame name bounds

* replace previous private methods for getting elements at x,y

* arrow bound text hit detection

* keep iframes on top

* remove dependence on old collision methods from app

* remove old collision functions

* move some hit functions outside of app

* code refactor

* type

* text collision from inside

* fix context menu test

* highest z-index collision

* fix 1px away binding test

* strictly less

* remove unused imports

* lint

* 'ignore' resize flipping test

* more lint fix

* skip 'flips while resizing' test

* more test

* fix merge errors

* fix selection in resize test

* added a bit more comment

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-04-04 16:31:23 +08:00
Excalidraw Bot
4c04ce1c48 Auto commit: Calculate translation coverage 2024-04-03 13:45:31 +00:00
Excalidraw Bot
a464402919 New translations en.json (Hebrew) 2024-04-03 15:45:17 +02:00
Excalidraw Bot
be18f35595 Auto commit: Calculate translation coverage 2024-04-03 12:16:58 +00:00
Excalidraw Bot
b4f9ee520a New translations en.json (Hebrew) 2024-04-03 14:16:29 +02:00
Excalidraw Bot
455153d728 Auto commit: Calculate translation coverage 2024-04-01 06:34:04 +00:00
Excalidraw Bot
1353ef62b8 New translations en.json (Marathi) 2024-04-01 08:33:49 +02:00
Excalidraw Bot
6fad1e745a New translations en.json (Hindi) 2024-04-01 08:33:48 +02:00
Excalidraw Bot
2c988961f7 New translations en.json (Marathi) 2024-04-01 07:08:38 +02:00
Excalidraw Bot
2cd9a7697f New translations en.json (Hindi) 2024-04-01 07:08:37 +02:00
Excalidraw Bot
d398528493 Auto commit: Calculate translation coverage 2024-03-30 11:18:17 +00:00
Excalidraw Bot
59fe6e7b6d New translations en.json (Marathi) 2024-03-30 12:18:05 +01:00
Excalidraw Bot
abaf858f6c Auto commit: Calculate translation coverage 2024-03-29 14:45:52 +00:00
Excalidraw Bot
949c5b7af1 New translations en.json (Marathi) 2024-03-29 15:45:40 +01:00
Excalidraw Bot
701eb7f9fd Auto commit: Calculate translation coverage 2024-03-29 10:31:55 +00:00
Excalidraw Bot
07d92f720b New translations en.json (Catalan) 2024-03-29 11:31:42 +01:00
Excalidraw Bot
d16b808bb9 Auto commit: Calculate translation coverage 2024-03-29 09:27:55 +00:00
Excalidraw Bot
b2e09157da New translations en.json (Chinese Traditional) 2024-03-29 10:27:44 +01:00
Excalidraw Bot
93ee60cd9b New translations en.json (Romanian) 2024-03-29 10:27:43 +01:00
Excalidraw Bot
9eb509e068 New translations en.json (Chinese Simplified) 2024-03-29 10:27:42 +01:00
Excalidraw Bot
89f3dfb399 New translations en.json (Slovak) 2024-03-29 10:27:41 +01:00
Excalidraw Bot
a4c9355b03 Auto commit: Calculate translation coverage 2024-03-29 07:56:59 +00:00
Excalidraw Bot
c79cdab613 New translations en.json (Chinese Traditional) 2024-03-29 08:56:48 +01:00
Excalidraw Bot
ae3735a150 Auto commit: Calculate translation coverage 2024-03-29 04:28:08 +00:00
Excalidraw Bot
38a5c6c01a New translations en.json (Russian) 2024-03-29 05:27:57 +01:00
Excalidraw Bot
68caccfc2a Auto commit: Calculate translation coverage 2024-03-29 01:11:19 +00:00
Excalidraw Bot
9482c7adc6 New translations en.json (Swedish) 2024-03-29 02:11:07 +01:00
Excalidraw Bot
ff23a04e27 Auto commit: Calculate translation coverage 2024-03-29 00:01:13 +00:00
Excalidraw Bot
9ea989ee2a New translations en.json (Swedish) 2024-03-29 01:01:01 +01:00
Excalidraw Bot
261bff5bea Auto commit: Calculate translation coverage 2024-03-28 21:45:56 +00:00
Excalidraw Bot
55740254ed New translations en.json (German) 2024-03-28 22:45:44 +01:00
Excalidraw Bot
acb4da9f5c Auto commit: Calculate translation coverage 2024-03-28 20:46:08 +00:00
Excalidraw Bot
78131cf48b New translations en.json (Occitan) 2024-03-28 21:45:52 +01:00
Excalidraw Bot
415d5d6f6a Auto commit: Calculate translation coverage 2024-03-28 19:44:22 +00:00
Excalidraw Bot
0789a3db47 New translations en.json (Slovenian) 2024-03-28 20:44:05 +01:00
Excalidraw Bot
7218ddea85 Auto commit: Calculate translation coverage 2024-03-28 18:27:06 +00:00
Excalidraw Bot
e94ca414fb New translations en.json (Slovenian) 2024-03-28 19:26:45 +01:00
Excalidraw Bot
2b374bfa3d New translations en.json (German) 2024-03-28 19:26:36 +01:00
David Luzar
3e334a67ed feat: show firefox-compatible command palette shortcut alias (#7825) 2024-03-28 18:12:54 +01:00
Excalidraw Bot
a140db6244 Auto commit: Calculate translation coverage 2024-03-28 17:01:41 +00:00
Excalidraw Bot
07c0753d38 New translations en.json (Karakalpak) 2024-03-28 18:00:31 +01:00
Excalidraw Bot
26f3b861d7 New translations en.json (Kabyle) 2024-03-28 18:00:30 +01:00
Excalidraw Bot
f115a98333 New translations en.json (Occitan) 2024-03-28 18:00:29 +01:00
Excalidraw Bot
f45779c41c New translations en.json (Norwegian Bokmal) 2024-03-28 18:00:28 +01:00
Excalidraw Bot
8446097251 New translations en.json (Uzbek) 2024-03-28 18:00:27 +01:00
Excalidraw Bot
812dfcf633 New translations en.json (Sinhala) 2024-03-28 18:00:26 +01:00
Excalidraw Bot
7b3dcf2f03 New translations en.json (Chinese Traditional, Hong Kong) 2024-03-28 18:00:25 +01:00
Excalidraw Bot
aa27d5f8d1 New translations en.json (Burmese) 2024-03-28 18:00:24 +01:00
Excalidraw Bot
610ee586cb New translations en.json (Azerbaijani) 2024-03-28 18:00:23 +01:00
Excalidraw Bot
7f56e24078 New translations en.json (Latvian) 2024-03-28 18:00:22 +01:00
Excalidraw Bot
07bb8c524e New translations en.json (Kazakh) 2024-03-28 18:00:21 +01:00
Excalidraw Bot
9bed7b2086 New translations en.json (Norwegian Nynorsk) 2024-03-28 18:00:20 +01:00
Excalidraw Bot
5c5e6b851c New translations en.json (Thai) 2024-03-28 18:00:19 +01:00
Excalidraw Bot
ca415bca50 New translations en.json (Marathi) 2024-03-28 18:00:18 +01:00
Excalidraw Bot
7d6293d5a0 New translations en.json (Bengali) 2024-03-28 18:00:17 +01:00
Excalidraw Bot
0d35449faa New translations en.json (Tamil) 2024-03-28 18:00:16 +01:00
Excalidraw Bot
dd33aefac3 New translations en.json (Khmer) 2024-03-28 18:00:15 +01:00
Excalidraw Bot
8e137d1f72 New translations en.json (Persian) 2024-03-28 18:00:14 +01:00
Excalidraw Bot
2888c3bb6e New translations en.json (Indonesian) 2024-03-28 18:00:13 +01:00
Excalidraw Bot
aaef4e3402 New translations en.json (Portuguese, Brazilian) 2024-03-28 18:00:12 +01:00
Excalidraw Bot
8b0a35c832 New translations en.json (Galician) 2024-03-28 18:00:11 +01:00
Excalidraw Bot
ce2da48663 New translations en.json (Vietnamese) 2024-03-28 18:00:10 +01:00
Excalidraw Bot
869b89c136 New translations en.json (Chinese Traditional) 2024-03-28 18:00:09 +01:00
Excalidraw Bot
8bcbecc0ec New translations en.json (Ukrainian) 2024-03-28 18:00:08 +01:00
Excalidraw Bot
c7a0557e98 New translations en.json (Turkish) 2024-03-28 18:00:07 +01:00
Excalidraw Bot
c5e75439e4 New translations en.json (Slovenian) 2024-03-28 18:00:06 +01:00
Excalidraw Bot
8a07b5b907 New translations en.json (Russian) 2024-03-28 18:00:05 +01:00
Excalidraw Bot
584170eec3 New translations en.json (Portuguese) 2024-03-28 18:00:04 +01:00
Excalidraw Bot
6dd2501a19 New translations en.json (Polish) 2024-03-28 18:00:03 +01:00
Excalidraw Bot
3c3c1e9f8c New translations en.json (Punjabi) 2024-03-28 18:00:02 +01:00
Excalidraw Bot
17b01dec90 New translations en.json (Dutch) 2024-03-28 18:00:01 +01:00
Excalidraw Bot
eb4d64dcd8 New translations en.json (Lithuanian) 2024-03-28 17:59:59 +01:00
Excalidraw Bot
dc9f20c19e New translations en.json (Kurdish) 2024-03-28 17:59:59 +01:00
Excalidraw Bot
7c40b5ae3e New translations en.json (Korean) 2024-03-28 17:59:58 +01:00
Excalidraw Bot
bda85ff7ef New translations en.json (Japanese) 2024-03-28 17:59:57 +01:00
Excalidraw Bot
68b1bd80fa New translations en.json (Hungarian) 2024-03-28 17:59:56 +01:00
Excalidraw Bot
5771f5c0b7 New translations en.json (Hebrew) 2024-03-28 17:59:55 +01:00
Excalidraw Bot
fbbd953f42 New translations en.json (Finnish) 2024-03-28 17:59:53 +01:00
Excalidraw Bot
8d7e8e89db New translations en.json (Basque) 2024-03-28 17:59:53 +01:00
Excalidraw Bot
4e52529cbb New translations en.json (Greek) 2024-03-28 17:59:52 +01:00
Excalidraw Bot
a77c7bb41a New translations en.json (German) 2024-03-28 17:59:51 +01:00
Excalidraw Bot
5e2cdeb699 New translations en.json (Danish) 2024-03-28 17:59:50 +01:00
Excalidraw Bot
4d077f7324 New translations en.json (Czech) 2024-03-28 17:59:49 +01:00
Excalidraw Bot
7fda1f04cf New translations en.json (Catalan) 2024-03-28 17:59:48 +01:00
Excalidraw Bot
bce1d4a0e8 New translations en.json (Bulgarian) 2024-03-28 17:59:47 +01:00
Excalidraw Bot
cecd042357 New translations en.json (Arabic) 2024-03-28 17:59:46 +01:00
Excalidraw Bot
e4047f89c9 New translations en.json (Spanish) 2024-03-28 17:59:45 +01:00
Excalidraw Bot
1b457b3efd New translations en.json (French) 2024-03-28 17:59:44 +01:00
Excalidraw Bot
99fe0df4b1 New translations en.json (Romanian) 2024-03-28 17:59:43 +01:00
Excalidraw Bot
9f3209c487 New translations en.json (Hindi) 2024-03-28 17:59:42 +01:00
Excalidraw Bot
4388c33cd4 New translations en.json (Chinese Simplified) 2024-03-28 17:59:41 +01:00
Excalidraw Bot
3e5c45f674 New translations en.json (Swedish) 2024-03-28 17:59:40 +01:00
Excalidraw Bot
85bc583696 New translations en.json (Slovak) 2024-03-28 17:59:40 +01:00
Excalidraw Bot
2d2c35b6db New translations en.json (Italian) 2024-03-28 17:59:39 +01:00
David Luzar
1d71f84515 fix: stop using lookbehind for backwards compat (#7824) 2024-03-28 17:32:38 +01:00
Ryan Di
550a388b2b feat: command palette (#7804)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-03-28 16:16:32 +00:00
David Luzar
6b523563d8 fix: ejs support in html files (#7822) 2024-03-28 14:58:47 +01:00
David Luzar
65bc500598 fix: excalidrawAPI.toggleSidebar not switching between tabs correctly (#7821) 2024-03-28 14:52:23 +01:00
Aakansha Doshi
7949aa1f1c feat: upgrade mermaid-to-excalidraw to 0.3.0 (#7819) 2024-03-28 16:44:29 +05:30
Excalidraw Bot
b3bc9b9513 Auto commit: Calculate translation coverage 2024-03-21 10:59:59 +00:00
Excalidraw Bot
ad5c655b32 New translations en.json (Hebrew) 2024-03-21 11:59:41 +01:00
Excalidraw Bot
b91e6b5e4e New translations en.json (Swedish) 2024-03-19 08:12:42 +01:00
Excalidraw Bot
06ca0a66de New translations en.json (Chinese Simplified) 2024-03-18 22:31:28 +01:00
Excalidraw Bot
f170f8dfc2 New translations en.json (Chinese Traditional) 2024-03-18 19:47:46 +01:00
Excalidraw Bot
b6b7518992 New translations en.json (Marathi) 2024-03-18 15:47:50 +01:00
Excalidraw Bot
be7b9ce46b New translations en.json (German) 2024-03-18 15:47:49 +01:00
Excalidraw Bot
743ae9bef1 New translations en.json (Hindi) 2024-03-18 15:47:48 +01:00
Excalidraw Bot
1616535de5 New translations en.json (Catalan) 2024-03-18 14:27:10 +01:00
Excalidraw Bot
18471dbdc8 New translations en.json (Slovenian) 2024-03-18 13:01:13 +01:00
Excalidraw Bot
2c9302b33f New translations en.json (Russian) 2024-03-18 13:01:12 +01:00
Excalidraw Bot
f60ae05858 New translations en.json (Catalan) 2024-03-18 13:01:11 +01:00
Excalidraw Bot
b14aeed40e New translations en.json (Romanian) 2024-03-18 13:01:10 +01:00
Excalidraw Bot
28a2f33bd3 New translations en.json (Karakalpak) 2024-03-18 11:07:38 +01:00
Excalidraw Bot
8183c9a2b9 New translations en.json (Kabyle) 2024-03-18 11:07:37 +01:00
Excalidraw Bot
449f57c0c9 New translations en.json (Occitan) 2024-03-18 11:07:36 +01:00
Excalidraw Bot
6d3f9b1da1 New translations en.json (Norwegian Bokmal) 2024-03-18 11:07:35 +01:00
Excalidraw Bot
a4f9983250 New translations en.json (Uzbek) 2024-03-18 11:07:34 +01:00
Excalidraw Bot
cd6f1e7e25 New translations en.json (Sinhala) 2024-03-18 11:07:33 +01:00
Excalidraw Bot
fc5668fed0 New translations en.json (Chinese Traditional, Hong Kong) 2024-03-18 11:07:32 +01:00
Excalidraw Bot
6cf27e310f New translations en.json (Burmese) 2024-03-18 11:07:31 +01:00
Excalidraw Bot
1291a341f1 New translations en.json (Azerbaijani) 2024-03-18 11:07:30 +01:00
Excalidraw Bot
989b774e9d New translations en.json (Latvian) 2024-03-18 11:07:29 +01:00
Excalidraw Bot
372ef53228 New translations en.json (Kazakh) 2024-03-18 11:07:29 +01:00
Excalidraw Bot
279c446ca8 New translations en.json (Norwegian Nynorsk) 2024-03-18 11:07:28 +01:00
Excalidraw Bot
afa96620bc New translations en.json (Thai) 2024-03-18 11:07:27 +01:00
Excalidraw Bot
acf3847f8d New translations en.json (Marathi) 2024-03-18 11:07:26 +01:00
Excalidraw Bot
8882514053 New translations en.json (Bengali) 2024-03-18 11:07:25 +01:00
Excalidraw Bot
2eabd48630 New translations en.json (Tamil) 2024-03-18 11:07:24 +01:00
Excalidraw Bot
b4f90ab130 New translations en.json (Khmer) 2024-03-18 11:07:23 +01:00
Excalidraw Bot
e3698ae541 New translations en.json (Persian) 2024-03-18 11:07:22 +01:00
Excalidraw Bot
4cccf1b413 New translations en.json (Indonesian) 2024-03-18 11:07:21 +01:00
Excalidraw Bot
e168710885 New translations en.json (Portuguese, Brazilian) 2024-03-18 11:07:20 +01:00
Excalidraw Bot
955892aeec New translations en.json (Galician) 2024-03-18 11:07:19 +01:00
Excalidraw Bot
a574f4d2e9 New translations en.json (Vietnamese) 2024-03-18 11:07:18 +01:00
Excalidraw Bot
022b39c858 New translations en.json (Chinese Traditional) 2024-03-18 11:07:17 +01:00
Excalidraw Bot
7f1bfe6179 New translations en.json (Ukrainian) 2024-03-18 11:07:16 +01:00
Excalidraw Bot
de6b632fa3 New translations en.json (Turkish) 2024-03-18 11:07:15 +01:00
Excalidraw Bot
8a5de5b143 New translations en.json (Slovenian) 2024-03-18 11:07:15 +01:00
Excalidraw Bot
3cae9483b0 New translations en.json (Russian) 2024-03-18 11:07:14 +01:00
Excalidraw Bot
0c65e60ed1 New translations en.json (Portuguese) 2024-03-18 11:07:12 +01:00
Excalidraw Bot
f85ccc1a88 New translations en.json (Polish) 2024-03-18 11:07:12 +01:00
Excalidraw Bot
22d9a24ae6 New translations en.json (Punjabi) 2024-03-18 11:07:11 +01:00
Excalidraw Bot
f181775371 New translations en.json (Dutch) 2024-03-18 11:07:10 +01:00
Excalidraw Bot
a5fbefdc84 New translations en.json (Lithuanian) 2024-03-18 11:07:09 +01:00
Excalidraw Bot
d1b10f6276 New translations en.json (Kurdish) 2024-03-18 11:07:08 +01:00
Excalidraw Bot
a04a4a42ed New translations en.json (Korean) 2024-03-18 11:07:07 +01:00
Excalidraw Bot
a18159226a New translations en.json (Japanese) 2024-03-18 11:07:06 +01:00
Excalidraw Bot
0646e4453c New translations en.json (Hungarian) 2024-03-18 11:07:05 +01:00
Excalidraw Bot
2352af7196 New translations en.json (Hebrew) 2024-03-18 11:07:04 +01:00
Excalidraw Bot
46a6886ac4 New translations en.json (Finnish) 2024-03-18 11:07:03 +01:00
Excalidraw Bot
3ddf1c179a New translations en.json (Basque) 2024-03-18 11:07:02 +01:00
Excalidraw Bot
a0b2a0e4e6 New translations en.json (Greek) 2024-03-18 11:07:01 +01:00
Excalidraw Bot
43c46052f3 New translations en.json (German) 2024-03-18 11:07:00 +01:00
Excalidraw Bot
e8832fcb28 New translations en.json (Danish) 2024-03-18 11:06:59 +01:00
Excalidraw Bot
bd02772edb New translations en.json (Czech) 2024-03-18 11:06:58 +01:00
Excalidraw Bot
d5a38f3799 New translations en.json (Catalan) 2024-03-18 11:06:57 +01:00
Excalidraw Bot
921dca9f5b New translations en.json (Bulgarian) 2024-03-18 11:06:56 +01:00
Excalidraw Bot
8899453891 New translations en.json (Arabic) 2024-03-18 11:06:55 +01:00
Excalidraw Bot
7392af03a3 New translations en.json (Spanish) 2024-03-18 11:06:54 +01:00
Excalidraw Bot
7d1f4deb27 New translations en.json (French) 2024-03-18 11:06:53 +01:00
Excalidraw Bot
66724ac81d New translations en.json (Romanian) 2024-03-18 11:06:52 +01:00
Excalidraw Bot
2368d34ab3 New translations en.json (Hindi) 2024-03-18 11:06:52 +01:00
Excalidraw Bot
ddc2d8d2b7 New translations en.json (Chinese Simplified) 2024-03-18 11:06:51 +01:00
Excalidraw Bot
a7012a4b8e New translations en.json (Swedish) 2024-03-18 11:06:50 +01:00
Excalidraw Bot
88db54e11c New translations en.json (Slovak) 2024-03-18 11:06:49 +01:00
Excalidraw Bot
bc85f580ec New translations en.json (Italian) 2024-03-18 11:06:48 +01:00
David Luzar
15bfa626b4 feat: support to not render remote cursor & username (#7130) 2024-03-18 10:41:06 +01:00
David Luzar
068895db0e feat: expose more collaborator status icons (#7777) 2024-03-18 10:20:07 +01:00
Excalidraw Bot
02fd58ffc8 New translations en.json (Hindi) 2024-03-18 03:49:55 +01:00
dwelle
b7babe554b feat: load old library if migration fails 2024-03-11 09:57:01 +01:00
dwelle
6a385d6663 feat: change LibraryPersistenceAdapter load() source -> priority
to clarify the semantics
2024-03-11 09:40:51 +01:00
Excalidraw Bot
93af0ce89d New translations en.json (Swedish) 2024-03-11 07:35:54 +01:00
Excalidraw Bot
1c025c166a New translations en.json (Polish) 2024-03-09 23:01:20 +01:00
Excalidraw Bot
150e0cef5d New translations en.json (Polish) 2024-03-09 22:05:45 +01:00
Excalidraw Bot
7f40852b11 New translations en.json (Bengali) 2024-03-09 20:53:27 +01:00
Excalidraw Bot
0b6fae0243 New translations en.json (Chinese Traditional) 2024-03-09 20:53:26 +01:00
Excalidraw Bot
37af96a577 New translations en.json (Bengali) 2024-03-09 19:49:38 +01:00
Excalidraw Bot
0e718265fa New translations en.json (Romanian) 2024-03-09 14:22:26 +01:00
Excalidraw Bot
16b103151b New translations en.json (German) 2024-03-09 08:30:33 +01:00
Excalidraw Bot
351db6e2b9 New translations en.json (Russian) 2024-03-09 07:34:41 +01:00
Excalidraw Bot
b2fb87cd40 New translations en.json (Marathi) 2024-03-09 06:18:09 +01:00
Excalidraw Bot
388ec9f4db New translations en.json (Hindi) 2024-03-09 06:18:08 +01:00
Excalidraw Bot
95dd7f0617 New translations en.json (Chinese Simplified) 2024-03-09 06:18:07 +01:00
Excalidraw Bot
2349b9dcfe New translations en.json (Slovenian) 2024-03-09 00:41:58 +01:00
Excalidraw Bot
ddd05ff030 New translations en.json (Karakalpak) 2024-03-08 22:39:03 +01:00
Excalidraw Bot
4bc30fda19 New translations en.json (Kabyle) 2024-03-08 22:39:02 +01:00
Excalidraw Bot
285744877c New translations en.json (Occitan) 2024-03-08 22:39:01 +01:00
Excalidraw Bot
2169ac6fba New translations en.json (Norwegian Bokmal) 2024-03-08 22:39:00 +01:00
Excalidraw Bot
d2b9034f5e New translations en.json (Uzbek) 2024-03-08 22:38:59 +01:00
Excalidraw Bot
f1bbd3c5a0 New translations en.json (Sinhala) 2024-03-08 22:38:58 +01:00
Excalidraw Bot
aec87f706b New translations en.json (Chinese Traditional, Hong Kong) 2024-03-08 22:38:57 +01:00
Excalidraw Bot
7bd06eef1b New translations en.json (Burmese) 2024-03-08 22:38:56 +01:00
Excalidraw Bot
3be12ef66c New translations en.json (Azerbaijani) 2024-03-08 22:38:55 +01:00
Excalidraw Bot
8dae7772b0 New translations en.json (Latvian) 2024-03-08 22:38:54 +01:00
Excalidraw Bot
f69532aebf New translations en.json (Kazakh) 2024-03-08 22:38:53 +01:00
Excalidraw Bot
5f4e421001 New translations en.json (Norwegian Nynorsk) 2024-03-08 22:38:52 +01:00
Excalidraw Bot
b350917852 New translations en.json (Thai) 2024-03-08 22:38:51 +01:00
Excalidraw Bot
d3d1e21107 New translations en.json (Marathi) 2024-03-08 22:38:50 +01:00
Excalidraw Bot
11a7d52578 New translations en.json (Bengali) 2024-03-08 22:38:49 +01:00
Excalidraw Bot
d8a4736c01 New translations en.json (Tamil) 2024-03-08 22:38:49 +01:00
Excalidraw Bot
2a4b70e26c New translations en.json (Khmer) 2024-03-08 22:38:47 +01:00
Excalidraw Bot
353c17dc3b New translations en.json (Persian) 2024-03-08 22:38:46 +01:00
Excalidraw Bot
f51efffd3a New translations en.json (Indonesian) 2024-03-08 22:38:45 +01:00
Excalidraw Bot
2618178a93 New translations en.json (Portuguese, Brazilian) 2024-03-08 22:38:44 +01:00
Excalidraw Bot
c57d36ba38 New translations en.json (Galician) 2024-03-08 22:38:44 +01:00
Excalidraw Bot
6fa91ecb5c New translations en.json (Vietnamese) 2024-03-08 22:38:43 +01:00
Excalidraw Bot
44d61bcb62 New translations en.json (Chinese Traditional) 2024-03-08 22:38:42 +01:00
Excalidraw Bot
dfeddba61b New translations en.json (Ukrainian) 2024-03-08 22:38:41 +01:00
Excalidraw Bot
d691aa87ce New translations en.json (Turkish) 2024-03-08 22:38:40 +01:00
Excalidraw Bot
5a56bbb01d New translations en.json (Slovenian) 2024-03-08 22:38:39 +01:00
Excalidraw Bot
675adb6f0d New translations en.json (Russian) 2024-03-08 22:38:38 +01:00
Excalidraw Bot
4969de2250 New translations en.json (Portuguese) 2024-03-08 22:38:37 +01:00
Excalidraw Bot
8f6d5b3871 New translations en.json (Polish) 2024-03-08 22:38:36 +01:00
Excalidraw Bot
7732cd1d87 New translations en.json (Punjabi) 2024-03-08 22:38:35 +01:00
Excalidraw Bot
a166aa0ac5 New translations en.json (Dutch) 2024-03-08 22:38:34 +01:00
Excalidraw Bot
51fe6a8203 New translations en.json (Lithuanian) 2024-03-08 22:38:33 +01:00
Excalidraw Bot
287c3fce76 New translations en.json (Kurdish) 2024-03-08 22:38:32 +01:00
Excalidraw Bot
b78404bd85 New translations en.json (Korean) 2024-03-08 22:38:31 +01:00
Excalidraw Bot
1e2cc0b6f1 New translations en.json (Japanese) 2024-03-08 22:38:30 +01:00
Excalidraw Bot
be303375c4 New translations en.json (Hungarian) 2024-03-08 22:38:29 +01:00
Excalidraw Bot
8ba188e429 New translations en.json (Hebrew) 2024-03-08 22:38:28 +01:00
Excalidraw Bot
10842ae839 New translations en.json (Finnish) 2024-03-08 22:38:27 +01:00
Excalidraw Bot
592b9862e1 New translations en.json (Basque) 2024-03-08 22:38:27 +01:00
Excalidraw Bot
01b44663e3 New translations en.json (Greek) 2024-03-08 22:38:26 +01:00
Excalidraw Bot
ce59dd6d07 New translations en.json (German) 2024-03-08 22:38:25 +01:00
Excalidraw Bot
199d0eec81 New translations en.json (Danish) 2024-03-08 22:38:24 +01:00
Excalidraw Bot
176558d6d6 New translations en.json (Czech) 2024-03-08 22:38:22 +01:00
Excalidraw Bot
94da21229b New translations en.json (Catalan) 2024-03-08 22:38:21 +01:00
Excalidraw Bot
58298a9758 New translations en.json (Bulgarian) 2024-03-08 22:38:20 +01:00
Excalidraw Bot
bc53ef2017 New translations en.json (Arabic) 2024-03-08 22:38:19 +01:00
Excalidraw Bot
2892c5d77d New translations en.json (Spanish) 2024-03-08 22:38:19 +01:00
Excalidraw Bot
833e83d57d New translations en.json (French) 2024-03-08 22:38:17 +01:00
Excalidraw Bot
47369822d8 New translations en.json (Romanian) 2024-03-08 22:38:16 +01:00
Excalidraw Bot
2da836df9d New translations en.json (Hindi) 2024-03-08 22:38:15 +01:00
Excalidraw Bot
c42d3700f0 New translations en.json (Chinese Simplified) 2024-03-08 22:38:14 +01:00
Excalidraw Bot
146c599e43 New translations en.json (Swedish) 2024-03-08 22:38:13 +01:00
Excalidraw Bot
950651ce0a New translations en.json (Slovak) 2024-03-08 22:38:12 +01:00
Excalidraw Bot
50ef5d664c New translations en.json (Italian) 2024-03-08 22:38:11 +01:00
David Luzar
2382fad4f6 feat: store library to IndexedDB & support storage adapters (#7655) 2024-03-08 22:29:19 +01:00
Excalidraw Bot
1d1c6f35fa New translations en.json (Hindi) 2024-03-07 18:46:48 +01:00
Marcel Mraz
480572f893 fix: correcting Assistant metrics (#7758)
* Changed Assistant metrics to the corrrect ones from OS/2 table

* Adding more information about font metrics

* Adding branded types to avoid future mistakes
2024-03-07 16:54:36 +01:00
David Luzar
68b1fdb20e fix: add missing font metrics for Assistant (#7752) 2024-03-06 10:53:37 +01:00
David Luzar
a38e82f999 feat: close dropdown on escape (#7750) 2024-03-05 23:22:34 +01:00
David Luzar
a07f6e9e3a feat: show ai badge for discovery (#7749) 2024-03-05 23:22:25 +01:00
Marcel Mraz
7e471b55eb feat: text measurements based on font metrics (#7693)
* Introduced vertical offset based on harcoded font metrics 

* Unified usage of alphabetic baseline for both canvas & svg export

* Removed baseline property

* Removed font-size rounding on Safari

* Removed artificial width offset
2024-03-05 19:33:27 +00:00
Excalidraw Bot
fd43439dab New translations en.json (Swedish) 2024-03-04 16:57:04 +01:00
Ryan Di
160440b860 feat: improve collab error notification (#7741)
* identify cause

* toast after dialog for error messages in collab

* remove comment

* shake tooltip instead for repeating collab errors

* clear collab error

* empty commit

* simplify & fix reset race condition

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-03-04 20:43:44 +08:00
Excalidraw Bot
84ae576ad0 Auto commit: Calculate translation coverage 2024-02-29 16:15:01 +00:00
Excalidraw Bot
bc32a00d6a New translations en.json (Slovak) 2024-02-29 17:14:47 +01:00
Aakansha Doshi
f207bd0a1c build: export types for @excalidraw/utils (#7736)
* build: export types for @excalidraw/utils

* fix

* add types
2024-02-29 15:43:04 +05:30
Aakansha Doshi
99601baffc build: create ESM build for utils package 🥳 (#7500)
* build: create ESM build for utils package

* add deps, exports and import.meta
2024-02-28 19:33:47 +05:30
Aakansha Doshi
af1a3d5b76 fix: export utils from excalidraw package in excalidraw library (#7731)
* fix: export utils from excalidraw package in excalidraw library

* don't export utils utilities

* fix import path

* fix export

* don't export export utilites

* fix export paths

* reexport utils from excalidraw package

* add exports from withinBounds

* fix path
2024-02-28 11:14:57 +05:30
Excalidraw Bot
441b2ff2fd Auto commit: Calculate translation coverage 2024-02-28 04:48:28 +00:00
Excalidraw Bot
941e350245 New translations en.json (Chinese Simplified) 2024-02-28 05:48:15 +01:00
Wabweni Brian
36e56267c9 docs: add missing closing angle bracket in integration.mdx (#7729)
Update integration.mdx: Fix missing closing angle bracket in code sample

 A closing angle bracket was missing in a code sample.

Original code:
<div style={{height:"500px", width:"500px"}}
    <Excalidraw />
</div>

Changes:

<div style={{height:"500px", width:"500px"}}>
    <Excalidraw />
</div>
2024-02-27 07:19:20 +00:00
Aakansha Doshi
b09b5cb5f4 fix: split renderScene so that locales aren't imported unnecessarily (#7718)
* fix: split renderScene so that locales aren't imported unnecessarily

* lint

* split export code

* rename renderScene to helpers.ts

* add helpers

* fix typo

* fixes

* move renderElementToSvg to export

* lint

* rename export to staticSvgScene

* fix
2024-02-27 10:37:44 +05:30
Excalidraw Bot
e32290e9e1 Auto commit: Calculate translation coverage 2024-02-26 16:46:46 +00:00
Excalidraw Bot
231a806257 New translations en.json (Italian) 2024-02-26 17:46:32 +01:00
Excalidraw Bot
782daddfcc Auto commit: Calculate translation coverage 2024-02-26 15:47:06 +00:00
Excalidraw Bot
51ea204cb7 New translations en.json (Italian) 2024-02-26 16:46:49 +01:00
Aashman Verma
dd8529743a docs: type mistake in integration of excalidraw (#7723) 2024-02-26 10:24:27 +01:00
Excalidraw Bot
606979a539 New translations en.json (Hindi) 2024-02-25 19:30:01 +01:00
Aakansha Doshi
f639d44a95 fix: remove dependency of t in blob.ts (#7717)
* remove dependency of t in blob.ts

* fix
2024-02-23 15:05:46 +05:30
Excalidraw Bot
f1a51e5512 New translations en.json (Hindi) 2024-02-22 16:05:51 +01:00
Excalidraw Bot
2275532d10 New translations en.json (Marathi) 2024-02-22 16:05:49 +01:00
Excalidraw Bot
2d03d9b667 New translations en.json (Swedish) 2024-02-22 11:33:28 +01:00
Excalidraw Bot
917d5c81e3 Auto commit: Calculate translation coverage 2024-02-21 21:18:11 +00:00
Excalidraw Bot
d67ffe20ea New translations en.json (Romanian) 2024-02-21 22:17:56 +01:00
Excalidraw Bot
5252cc6f11 Auto commit: Calculate translation coverage 2024-02-21 19:01:07 +00:00
Excalidraw Bot
f006df974d New translations en.json (Chinese Traditional) 2024-02-21 20:00:53 +01:00
Excalidraw Bot
7bd061d996 Auto commit: Calculate translation coverage 2024-02-21 18:05:14 +00:00
Excalidraw Bot
2a3aa69f35 New translations en.json (German) 2024-02-21 19:05:01 +01:00
Excalidraw Bot
5908d8c07e Auto commit: Calculate translation coverage 2024-02-21 16:36:25 +00:00
Excalidraw Bot
e0fce912d5 New translations en.json (Slovenian) 2024-02-21 17:36:11 +01:00
Excalidraw Bot
8a77638f67 Auto commit: Calculate translation coverage 2024-02-21 15:23:40 +00:00
Excalidraw Bot
d3c43fb648 New translations en.json (Karakalpak) 2024-02-21 16:22:40 +01:00
Excalidraw Bot
1974b49b52 New translations en.json (Kabyle) 2024-02-21 16:22:39 +01:00
Excalidraw Bot
e729048c98 New translations en.json (Occitan) 2024-02-21 16:22:38 +01:00
Excalidraw Bot
6164bd47f9 New translations en.json (Norwegian Bokmal) 2024-02-21 16:22:37 +01:00
Excalidraw Bot
791fbfa2e8 New translations en.json (Sinhala) 2024-02-21 16:22:36 +01:00
Excalidraw Bot
fbdbcedf33 New translations en.json (Chinese Traditional, Hong Kong) 2024-02-21 16:22:35 +01:00
Excalidraw Bot
ca7c470793 New translations en.json (Burmese) 2024-02-21 16:22:34 +01:00
Excalidraw Bot
cf787e8b72 New translations en.json (Hindi) 2024-02-21 16:22:33 +01:00
Excalidraw Bot
998789dbe8 New translations en.json (Azerbaijani) 2024-02-21 16:22:32 +01:00
Excalidraw Bot
1b7098b775 New translations en.json (Latvian) 2024-02-21 16:22:31 +01:00
Excalidraw Bot
152dcae5bc New translations en.json (Kazakh) 2024-02-21 16:22:29 +01:00
Excalidraw Bot
42f2e1c5c3 New translations en.json (Norwegian Nynorsk) 2024-02-21 16:22:29 +01:00
Excalidraw Bot
a986a4f0bf New translations en.json (Thai) 2024-02-21 16:22:27 +01:00
Excalidraw Bot
f2fc6ee067 New translations en.json (Marathi) 2024-02-21 16:22:26 +01:00
Excalidraw Bot
043503a739 New translations en.json (Bengali) 2024-02-21 16:22:25 +01:00
Excalidraw Bot
83cd933987 New translations en.json (Tamil) 2024-02-21 16:22:24 +01:00
Excalidraw Bot
9efa749059 New translations en.json (Khmer) 2024-02-21 16:22:23 +01:00
Excalidraw Bot
c8fb8f0b2e New translations en.json (Persian) 2024-02-21 16:22:22 +01:00
Excalidraw Bot
ec719c131f New translations en.json (Indonesian) 2024-02-21 16:22:21 +01:00
Excalidraw Bot
90375a2f12 New translations en.json (Portuguese, Brazilian) 2024-02-21 16:22:20 +01:00
Excalidraw Bot
6051275d0a New translations en.json (Chinese Traditional) 2024-02-21 16:22:19 +01:00
Excalidraw Bot
06f0c2388d New translations en.json (Chinese Simplified) 2024-02-21 16:22:18 +01:00
Excalidraw Bot
7051bac7d8 New translations en.json (Ukrainian) 2024-02-21 16:22:17 +01:00
Excalidraw Bot
44aa5856cd New translations en.json (Swedish) 2024-02-21 16:22:15 +01:00
Excalidraw Bot
374dc52601 New translations en.json (Slovenian) 2024-02-21 16:22:14 +01:00
Excalidraw Bot
46345e9956 New translations en.json (Slovak) 2024-02-21 16:22:13 +01:00
Excalidraw Bot
f3c02d4298 New translations en.json (Russian) 2024-02-21 16:22:13 +01:00
Excalidraw Bot
b4cedca7da New translations en.json (Portuguese) 2024-02-21 16:22:11 +01:00
Excalidraw Bot
deaf828e84 New translations en.json (Polish) 2024-02-21 16:22:10 +01:00
Excalidraw Bot
38a5698bc7 New translations en.json (Punjabi) 2024-02-21 16:22:09 +01:00
Excalidraw Bot
70af8a3fa5 New translations en.json (Dutch) 2024-02-21 16:22:08 +01:00
Excalidraw Bot
37b172c8ca New translations en.json (Lithuanian) 2024-02-21 16:22:07 +01:00
Excalidraw Bot
1eef380425 New translations en.json (Kurdish) 2024-02-21 16:22:06 +01:00
Excalidraw Bot
1dcf411626 New translations en.json (Korean) 2024-02-21 16:22:05 +01:00
Excalidraw Bot
378a97553c New translations en.json (Italian) 2024-02-21 16:22:04 +01:00
Excalidraw Bot
3246b04911 New translations en.json (Hungarian) 2024-02-21 16:22:03 +01:00
Excalidraw Bot
dda48a7d6a New translations en.json (Hebrew) 2024-02-21 16:22:02 +01:00
Excalidraw Bot
29153f0d8d New translations en.json (Finnish) 2024-02-21 16:22:01 +01:00
Excalidraw Bot
70c513f568 New translations en.json (Basque) 2024-02-21 16:22:00 +01:00
Excalidraw Bot
56f75b259c New translations en.json (Greek) 2024-02-21 16:21:58 +01:00
Excalidraw Bot
f94a3a7711 New translations en.json (German) 2024-02-21 16:21:57 +01:00
Excalidraw Bot
5a166ee235 New translations en.json (Danish) 2024-02-21 16:21:56 +01:00
Excalidraw Bot
0c199e42c8 New translations en.json (Czech) 2024-02-21 16:21:55 +01:00
Excalidraw Bot
a377f55d7f New translations en.json (Bulgarian) 2024-02-21 16:21:54 +01:00
Excalidraw Bot
c4759c8ca8 New translations en.json (Arabic) 2024-02-21 16:21:53 +01:00
Excalidraw Bot
9d19230033 New translations en.json (Spanish) 2024-02-21 16:21:52 +01:00
Excalidraw Bot
5aa2ec962b New translations en.json (French) 2024-02-21 16:21:51 +01:00
Excalidraw Bot
b21e7f0a70 New translations en.json (Romanian) 2024-02-21 16:21:50 +01:00
Excalidraw Bot
0056d274d5 New translations en.json (Uzbek) 2024-02-21 16:21:49 +01:00
Excalidraw Bot
cf5d7f3928 New translations en.json (Catalan) 2024-02-21 16:21:48 +01:00
Excalidraw Bot
058eed953e New translations en.json (Vietnamese) 2024-02-21 16:21:47 +01:00
Excalidraw Bot
5feb41624d New translations en.json (Turkish) 2024-02-21 16:21:46 +01:00
Excalidraw Bot
10a74bf607 New translations en.json (Galician) 2024-02-21 16:21:45 +01:00
Excalidraw Bot
0d1bb00270 New translations en.json (Japanese) 2024-02-21 16:21:44 +01:00
Aakansha Doshi
f5ab3e4e12 fix: remove dependency of t from clipboard and image (#7712)
* fix: remove dependency of t from clipboard and image

* pass errorMessage to copyTextToSystemClipboard where needed

* wrap copyTextToSystemClipboard and rethrow translated error in caller

* review fix

* typo
2024-02-21 19:45:33 +05:30
Aakansha Doshi
361a9449bb fix: remove scene hack from export.ts & remove pass elementsMap to getContainingFrame (#7713)
* fix: remove scene hack from export.ts as its not needed anymore

* remove

* pass elementsMap to getContainingFrame

* remove unused `mapElementIds` param

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-21 16:34:20 +05:30
Aakansha Doshi
2e719ff671 fix: decouple pure functions from hyperlink to prevent mermaid bundling (#7710)
* move hyperlink code into its folder

* move pure js functions to hyperlink/helpers and move actionLink to actions

* fix tests

* fix
2024-02-20 20:59:01 +05:30
Excalidraw Bot
506756f332 Auto commit: Calculate translation coverage 2024-02-20 03:48:35 +00:00
Excalidraw Bot
67239c874e New translations en.json (Uzbek) 2024-02-20 04:48:23 +01:00
Aakansha Doshi
79d9dc2f8f fix: make bounds independent of scene (#7679)
* fix: make bounds independent of scene

* pass only elements to getCommonBounds

* lint

* pass elementsMap to getVisibleAndNonSelectedElements
2024-02-19 19:39:14 +05:30
Excalidraw Bot
d6cf042764 Auto commit: Calculate translation coverage 2024-02-19 13:24:59 +00:00
Excalidraw Bot
8e5f3ca841 New translations en.json (Catalan) 2024-02-19 14:24:43 +01:00
Aakansha Doshi
9013c84524 fix: make LinearElementEditor independent of scene (#7670)
* fix: make LinearElementEditor independent of scene

* more fixes

* pass elements and elementsMap to maybeBindBindableElement,getHoveredElementForBinding,bindingBorderTest,getElligibleElementsForBindableElementAndWhere,isLinearElementEligibleForNewBindingByBindable

* replace `ElementsMap` with `NonDeletedSceneElementsMap` & remove unused params

* fix lint

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-19 11:49:01 +05:30
Aakansha Doshi
47f87f4ecb fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap (#7663)
* fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap

* lint

* fix

* use non deleted elements where possible

* use non deleted elements map in actions

* pass elementsMap instead of array to elementOverlapsWithFrame

* lint

* fix

* pass elementsMap to getElementsCorners

* pass elementsMap to getEligibleElementsForBinding

* pass elementsMap in bindOrUnbindSelectedElements and unbindLinearElements

* pass elementsMap in elementsAreInFrameBounds,elementOverlapsWithFrame,isCursorInFrame,getElementsInResizingFrame

* pass elementsMap in getElementsWithinSelection, getElementsCompletelyInFrame, isElementContainingFrame, getElementsInNewFrame

* pass elementsMap to getElementWithTransformHandleType

* pass elementsMap to getVisibleGaps, getMaximumGroups,getReferenceSnapPoints,snapDraggedElements

* lint

* pass elementsMap to bindTextToShapeAfterDuplication,bindLinearElementToElement,getTextBindableContainerAtPosition

* revert changes for bindTextToShapeAfterDuplication
2024-02-16 11:35:01 +05:30
Excalidraw Bot
41d325fdd8 Auto commit: Calculate translation coverage 2024-02-15 15:43:56 +00:00
Excalidraw Bot
6b6761f654 New translations en.json (Vietnamese) 2024-02-15 16:43:43 +01:00
Aakansha Doshi
73bf50e8a8 fix: remove t from getDefaultAppState and allow name to be nullable (#7666)
* fix: remove t and allow name to be nullable

* pass name as required prop

* remove Unnamed

* pass name to excalidrawPlus as well for better type safe

* render once we have excalidrawAPI to avoid defaulting

* rename `getAppName` -> `getName` (temporary)

* stop preventing editing filenames when `props.name` supplied

* keep `name` as optional param for export functions

* keep `appState.name` on `props.name` state separate

* fix lint

* assertive first

* fix lint

* Add TODO

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-02-15 11:11:18 +05:30
Excalidraw Bot
fc3ae973be Auto commit: Calculate translation coverage 2024-02-13 11:15:09 +00:00
Excalidraw Bot
0c3c4d4f22 New translations en.json (Galician) 2024-02-13 12:14:56 +01:00
Excalidraw Bot
4df91b980a Auto commit: Calculate translation coverage 2024-02-10 10:54:58 +00:00
Excalidraw Bot
3729104547 New translations en.json (Japanese) 2024-02-10 11:54:46 +01:00
Aakansha Doshi
48c3465b19 docs: release patch v0.17.3 (#7673)
* docs: release patch v0.17.3

* update cl
2024-02-09 19:29:50 +05:30
David Luzar
adc4c9f484 fix: prevent panning to trigger history on macos chrome (#7671) 2024-02-08 19:50:50 +01:00
YuBin, Hsu
def1df2c68 fix: keep customData when converting to ExcalidrawElement (#7656)
* feat: keep customData when converting to ExcalidrawElement (#7654)

* docs: add changelog for keeping customData when converting to ExcalidrawElement
2024-02-08 17:23:10 +05:30
Excalidraw Bot
9fd896c1d1 Auto commit: Calculate translation coverage 2024-02-06 19:24:30 +00:00
Excalidraw Bot
e6f4e1f027 New translations en.json (Portuguese) 2024-02-06 20:24:16 +01:00
Excalidraw Bot
35424f62ed New translations en.json (Swedish) 2024-02-06 09:32:24 +01:00
Excalidraw Bot
70943ae461 Auto commit: Calculate translation coverage 2024-02-05 13:44:35 +00:00
Excalidraw Bot
a976aa7123 New translations en.json (French) 2024-02-05 14:44:22 +01:00
Excalidraw Bot
e58111d93d New translations en.json (Russian) 2024-02-04 18:14:26 +01:00
Excalidraw Bot
311ebaa5a4 Auto commit: Calculate translation coverage 2024-02-04 10:18:20 +00:00
Excalidraw Bot
b058b2dff1 New translations en.json (Dutch) 2024-02-04 11:18:10 +01:00
Excalidraw Bot
6c77e76c4c Auto commit: Calculate translation coverage 2024-02-04 08:44:00 +00:00
Excalidraw Bot
691225f51a New translations en.json (Romanian) 2024-02-04 09:43:48 +01:00
Excalidraw Bot
d46c669f64 Auto commit: Calculate translation coverage 2024-02-03 23:48:17 +00:00
Excalidraw Bot
7f46da315f New translations en.json (Chinese Simplified) 2024-02-04 00:48:06 +01:00
Excalidraw Bot
b7e0d18fae Auto commit: Calculate translation coverage 2024-02-03 16:41:58 +00:00
Excalidraw Bot
f9095caa42 New translations en.json (German) 2024-02-03 17:41:47 +01:00
Excalidraw Bot
de5c825d01 Auto commit: Calculate translation coverage 2024-02-03 15:29:53 +00:00
Excalidraw Bot
5fd26d2a45 New translations en.json (Karakalpak) 2024-02-03 16:28:33 +01:00
Excalidraw Bot
06052b1f3e New translations en.json (Kabyle) 2024-02-03 16:28:32 +01:00
Excalidraw Bot
98b3fbbc18 New translations en.json (Norwegian Bokmal) 2024-02-03 16:28:31 +01:00
Excalidraw Bot
fd29c8dd44 New translations en.json (Sinhala) 2024-02-03 16:28:30 +01:00
Excalidraw Bot
f4e90f1888 New translations en.json (Chinese Traditional, Hong Kong) 2024-02-03 16:28:29 +01:00
Excalidraw Bot
d9d8a39d6a New translations en.json (Burmese) 2024-02-03 16:28:28 +01:00
Excalidraw Bot
aa1a99dcf2 New translations en.json (Azerbaijani) 2024-02-03 16:28:27 +01:00
Excalidraw Bot
01f863f268 New translations en.json (Latvian) 2024-02-03 16:28:26 +01:00
Excalidraw Bot
8779e7f36f New translations en.json (Kazakh) 2024-02-03 16:28:25 +01:00
Excalidraw Bot
703cfc02e9 New translations en.json (Norwegian Nynorsk) 2024-02-03 16:28:25 +01:00
Excalidraw Bot
d11c92ffc3 New translations en.json (Thai) 2024-02-03 16:28:24 +01:00
Excalidraw Bot
7f381a0d02 New translations en.json (Marathi) 2024-02-03 16:28:23 +01:00
Excalidraw Bot
b8b1b9d57f New translations en.json (Bengali) 2024-02-03 16:28:22 +01:00
Excalidraw Bot
103c0e5997 New translations en.json (Tamil) 2024-02-03 16:28:21 +01:00
Excalidraw Bot
696e3d6836 New translations en.json (Khmer) 2024-02-03 16:28:20 +01:00
Excalidraw Bot
07a6b9942e New translations en.json (Persian) 2024-02-03 16:28:19 +01:00
Excalidraw Bot
e3d2b854d7 New translations en.json (Indonesian) 2024-02-03 16:28:18 +01:00
Excalidraw Bot
5ee88f6c6b New translations en.json (Portuguese, Brazilian) 2024-02-03 16:28:17 +01:00
Excalidraw Bot
1681598c7d New translations en.json (Vietnamese) 2024-02-03 16:28:16 +01:00
Excalidraw Bot
8f6d92c45c New translations en.json (Chinese Traditional) 2024-02-03 16:28:15 +01:00
Excalidraw Bot
3445c340a1 New translations en.json (Chinese Simplified) 2024-02-03 16:28:14 +01:00
Excalidraw Bot
a82d3c15ff New translations en.json (Turkish) 2024-02-03 16:28:13 +01:00
Excalidraw Bot
8b44b2f2ed New translations en.json (Swedish) 2024-02-03 16:28:12 +01:00
Excalidraw Bot
3f4f9e914b New translations en.json (Slovenian) 2024-02-03 16:28:11 +01:00
Excalidraw Bot
721565f3c3 New translations en.json (Slovak) 2024-02-03 16:28:10 +01:00
Excalidraw Bot
4b8060b093 New translations en.json (Russian) 2024-02-03 16:28:10 +01:00
Excalidraw Bot
b61bbfea4e New translations en.json (Portuguese) 2024-02-03 16:28:09 +01:00
Excalidraw Bot
6c88eb12d7 New translations en.json (Polish) 2024-02-03 16:28:08 +01:00
Excalidraw Bot
5cb46022fb New translations en.json (Punjabi) 2024-02-03 16:28:07 +01:00
Excalidraw Bot
afa0f83349 New translations en.json (Dutch) 2024-02-03 16:28:06 +01:00
Excalidraw Bot
a3ddac93a6 New translations en.json (Lithuanian) 2024-02-03 16:28:05 +01:00
Excalidraw Bot
6dd1406716 New translations en.json (Kurdish) 2024-02-03 16:28:04 +01:00
Excalidraw Bot
59f11650f2 New translations en.json (Korean) 2024-02-03 16:28:03 +01:00
Excalidraw Bot
fb6e93fe8e New translations en.json (Italian) 2024-02-03 16:28:02 +01:00
Excalidraw Bot
b7ddf1ef3a New translations en.json (Hungarian) 2024-02-03 16:28:01 +01:00
Excalidraw Bot
5ffc582f76 New translations en.json (Hebrew) 2024-02-03 16:28:01 +01:00
Excalidraw Bot
d025f728cc New translations en.json (Finnish) 2024-02-03 16:28:00 +01:00
Excalidraw Bot
7172c833cb New translations en.json (Basque) 2024-02-03 16:27:59 +01:00
Excalidraw Bot
e22350f745 New translations en.json (Greek) 2024-02-03 16:27:58 +01:00
Excalidraw Bot
da9319411b New translations en.json (German) 2024-02-03 16:27:57 +01:00
Excalidraw Bot
a3bd43f3b2 New translations en.json (Danish) 2024-02-03 16:27:56 +01:00
Excalidraw Bot
4d0fd858be New translations en.json (Czech) 2024-02-03 16:27:55 +01:00
Excalidraw Bot
f89325507c New translations en.json (Bulgarian) 2024-02-03 16:27:54 +01:00
Excalidraw Bot
3cafe68e2b New translations en.json (Arabic) 2024-02-03 16:27:53 +01:00
Excalidraw Bot
e9ea414849 New translations en.json (Romanian) 2024-02-03 16:27:52 +01:00
Excalidraw Bot
fef5b41bd9 New translations en.json (Galician) 2024-02-03 16:27:51 +01:00
Excalidraw Bot
7a478bd508 New translations en.json (Japanese) 2024-02-03 16:27:50 +01:00
Excalidraw Bot
bba0033900 New translations en.json (Occitan) 2024-02-03 16:27:49 +01:00
Excalidraw Bot
2e773439ce New translations en.json (Hindi) 2024-02-03 16:27:48 +01:00
Excalidraw Bot
3ff668d7ed New translations en.json (French) 2024-02-03 16:27:47 +01:00
Excalidraw Bot
1801d9efcb New translations en.json (Catalan) 2024-02-03 16:27:46 +01:00
Excalidraw Bot
ecd9d7444f New translations en.json (Spanish) 2024-02-03 16:27:45 +01:00
Excalidraw Bot
2dc2b31e36 New translations en.json (Ukrainian) 2024-02-03 16:27:45 +01:00
David Luzar
0513b647ec feat: change collab trigger & add share dialog (#7647) 2024-02-03 14:04:23 +00:00
David Luzar
a289c42830 feat: add loading state to FilledButton (#7650) 2024-02-03 14:53:31 +01:00
David Luzar
d67eaa8710 fix: file save timing out with big file sizes (#7649) 2024-02-03 11:53:35 +01:00
Excalidraw Bot
50a5886455 Auto commit: Calculate translation coverage 2024-02-02 19:30:27 +00:00
Excalidraw Bot
8d4dde8411 New translations en.json (Galician) 2024-02-02 20:30:14 +01:00
Excalidraw Bot
b6c9bd6bfc Auto commit: Calculate translation coverage 2024-02-02 17:29:48 +00:00
Excalidraw Bot
a5977368b1 New translations en.json (Occitan) 2024-02-02 18:29:35 +01:00
Aakansha Doshi
0c3dffb082 fix: make getEmbedLink independent of t function (#7643)
* fix: make getEmbedLink independent of t function

* rename warning to error and make it type safe
2024-02-01 21:12:10 +05:30
Milos Vetesnik
0e0f34edd8 fix: follow mode border for hosts apps (#7642) 2024-02-01 15:03:15 +01:00
David Luzar
4888d9d355 chore: change default port of collab server (#7641) 2024-02-01 14:41:38 +01:00
Aakansha Doshi
1c39bd5781 fix: don't bundle react and jotai when importing from scene (#7640)
* don't bundle react and jotai when importing from scene

* fix
2024-02-01 18:24:17 +05:30
Aakansha Doshi
90ad885446 feat: support onPointerUp prop (#7638)
* feat: support onPointerUp prop

* update changelog

* Update packages/excalidraw/CHANGELOG.md

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>

---------

Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
2024-02-01 12:26:55 +00:00
Excalidraw Bot
401281d0eb New translations en.json (Japanese) 2024-02-01 10:44:58 +01:00
Aakansha Doshi
1741c234a6 fix: decouple container cache logic to containerCache. (#7637) 2024-01-31 21:17:41 +05:30
Aakansha Doshi
63b50b3586 fix: don't bundle react-dom when importing from transformHandles (#7634)
* fix: don't bundle react when importing from transfromHandles

* rename to DEFAULT_TRANSFORM_HANDLE_SPACING
2024-01-31 16:50:35 +05:30
Aakansha Doshi
e0fefa8025 fix: don't bundle react-dom when importing from element (#7635) 2024-01-31 16:43:37 +05:30
Excalidraw Bot
f7df761f7c Auto commit: Calculate translation coverage 2024-01-31 07:13:49 +00:00
Excalidraw Bot
e690653a3a New translations en.json (Occitan) 2024-01-31 08:13:38 +01:00
Excalidraw Bot
012094d32f New translations en.json (Hindi) 2024-01-30 03:20:20 +01:00
Milos Vetesnik
d426cc968d refactor: remove portal as it is no longer needed (#7623)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 16:37:09 +01:00
Excalidraw Bot
085099b770 Auto commit: Calculate translation coverage 2024-01-29 14:43:01 +00:00
Excalidraw Bot
c066a5d65a New translations en.json (French) 2024-01-29 15:42:49 +01:00
Aashir Israr
2409c091ff feat: support roundness for images (#7558)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 15:27:07 +01:00
Andran1k
626fe252ab fix: frame name field (#7457)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-29 10:57:22 +01:00
Excalidraw Bot
0bb4aa58a0 New translations en.json (Ukrainian) 2024-01-27 15:15:12 +01:00
Excalidraw Bot
3baf081831 New translations en.json (Ukrainian) 2024-01-27 14:18:19 +01:00
Excalidraw Bot
cd07cae68c Auto commit: Calculate translation coverage 2024-01-26 23:20:26 +00:00
Excalidraw Bot
f8862ff2b3 New translations en.json (Catalan) 2024-01-27 00:20:14 +01:00
Excalidraw Bot
79dd246722 New translations en.json (Ukrainian) 2024-01-26 18:01:08 +01:00
Excalidraw Bot
6ba4dd5d86 New translations en.json (Ukrainian) 2024-01-26 16:19:23 +01:00
Aakansha Doshi
10bd08ef19 fix: make getBoundTextElement and related helpers pure (#7601)
* fix: make getBoundTextElement pure

* updating args

* fix

* pass boundTextElement to getBoundTextMaxWidth

* fix labelled arrows

* lint

* pass elementsMap to removeElementsFromFrame

* pass elementsMap to getMaximumGroups, alignElements and distributeElements

* lint

* pass allElementsMap to renderElement

* lint

* feat: make more typesafe

* fix: remove unnecessary assertion

* fix: remove unused params

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-26 11:29:07 +05:30
Aakansha Doshi
2789d08154 docs: update the docs for next js integration (#7605)
* docs: update the docs for next js integration

* update

* update

* update docs with tabbed examples

* fix
2024-01-25 20:26:48 +05:30
Excalidraw Bot
da4896077b Auto commit: Calculate translation coverage 2024-01-25 01:58:25 +00:00
Excalidraw Bot
0321ea248a New translations en.json (Spanish) 2024-01-25 02:58:13 +01:00
dependabot[bot]
678bb2b819 build(deps-dev): bump vite from 5.0.6 to 5.0.12 (#7586)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.6 to 5.0.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-24 19:29:50 +05:30
dependabot[bot]
966f9aead9 build(deps-dev): bump vite from 5.0.6 to 5.0.12 in /examples/excalidraw/with-script-in-browser (#7603)
build(deps-dev): bump vite

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.6 to 5.0.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-24 19:28:11 +05:30
Aakansha Doshi
4f0a2a9593 docs: add next js with app router example (#7552)
* move the existing example to with-script-in-browser

* Add example with next js app router

* disable ssr for excalidraw client comp

* typo

* update output dir

* don't include nextjs example in tsconfig

* remove meta.json

* lint

* remove example.ts

* port

* move the examples outside packages and use the deps as workspaces in examples

* update gitignore

* fix example

* update path of build dir

* fix

* fix scripts

* try local path

* fix

* update commands

* fix

* fix

* fix script

* skip ts

* disable ts

* add vercel.json

* install

* update tsconfig

* fix lint

* remove console.log

* lets see if this works

* revert

* remove ts nocheck

* add types and some utils in nextjs example

* fix types

* updatw example and remove nextjs dynamic syntax so we don't import excal twice

* move both examples to workspaces and create generic example to be used by browser and next js both

* copy the static assets to nextjs

* fix ts config

* render custom menu items

* fix custom footer

* fix types in browser example

* use regular imports for importing excal and import it using dynamic next js in app router instead

* Add example for pages router

* fix css discrepancies

* fix css

* configure output dir

* fix

* fix css

* rename to with-nextjs

* move components to examples/excalidraw/components
2024-01-24 17:07:54 +05:30
halocean96
f3f8217125 docs: toggleSidebar api fix (#7575) 2024-01-23 14:50:51 +00:00
David Luzar
89bd6181f2 fix: revert mapElementIds flag removal (#7594) 2024-01-22 17:23:00 +01:00
Aakansha Doshi
c6fdac131b ci: add the workspace ignore check to install actions as dependency for auto release (#7593) 2024-01-22 17:01:00 +05:30
David Luzar
0415c616b1 refactor: decoupling global Scene state part-1 (#7577) 2024-01-22 00:23:02 +01:00
David Luzar
740a165452 fix: filter out elements not overlapping frame on paste (#7591) 2024-01-21 20:55:57 +01:00
Ryan Di
4997624a3a fix: frame name editing inconvenience (#7437) 2024-01-21 20:55:28 +01:00
Barnabás Molnár
b66daae1f3 fix: Truncate collaborator name in dropdown. (#7576) 2024-01-21 20:36:09 +01:00
David Luzar
1e7df58b5b feat: add pasted elements to frame under cursor (#7590) 2024-01-21 14:01:43 +01:00
David Luzar
46da032626 fix: exporting frame-overlapping elements belonging to other frames (#7584) 2024-01-19 14:41:22 +01:00
みけCAT
3b0593baa7 fix: Prevent the library label from being collapsed (#7579) 2024-01-19 14:41:08 +01:00
Excalidraw Bot
07415a37c9 Auto commit: Calculate translation coverage 2024-01-17 15:48:05 +00:00
Excalidraw Bot
356eb47ca3 New translations en.json (Japanese) 2024-01-17 16:47:46 +01:00
みけCAT
dd530737a2 docs: fix "canvas actions" link in Props page (#7536)
fix "canvas actions" link in Props page
2024-01-17 16:19:42 +05:30
Aakansha Doshi
a4e5e46dd1 fix: move default to last so its compatible with nextjs (#7561) 2024-01-15 14:52:04 +05:30
Excalidraw Bot
9383e1a983 Auto commit: Calculate translation coverage 2024-01-14 21:44:10 +00:00
Excalidraw Bot
43ad9a7da9 New translations en.json (Ukrainian) 2024-01-14 22:43:59 +01:00
Excalidraw Bot
b661158a85 Auto commit: Calculate translation coverage 2024-01-14 20:35:38 +00:00
Excalidraw Bot
4d5f89fb2a New translations en.json (Norwegian Nynorsk) 2024-01-14 21:35:25 +01:00
David Luzar
0fa5f5de4c fix: translating frames containing grouped text containers (#7557) 2024-01-13 21:28:54 +01:00
David Luzar
41cc746885 fix: host font assets from root (#7548) 2024-01-11 21:29:29 +01:00
David Luzar
8ead8559e0 feat: redirect font requests to cdn (#7549) 2024-01-11 21:08:17 +01:00
David Luzar
5245276409 feat: erase groups atomically (#7545) 2024-01-11 17:43:04 +01:00
David Luzar
0c24a7042f feat: remove ExcalidrawEmbeddableElement.validated flag (#7539) 2024-01-11 17:42:51 +01:00
Are
86cfeb714c feat: add eraser tool trail (#7511)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2024-01-11 16:10:15 +00:00
David Luzar
872973f145 fix: do not modify elements while erasing (#7531) 2024-01-11 16:00:07 +01:00
Aakansha Doshi
3ecf72a507 docs: add changelog for ESM build (#7542)
* docs: add changelog for ESM build

* move to breaking change
2024-01-11 16:40:45 +05:30
みけCAT
1aaa400876 docs: fix extra space in UIOptions/tools (#7537)
fix typo in UIOptions/tools
2024-01-11 11:09:33 +00:00
Aakansha Doshi
65047cc2cb fix: decouple react and react-dom imports from utils and make it treeshakeable (#7527)
fix: decouple react and react-dom imports from utils and make it tree-shakeable
2024-01-08 21:01:47 +05:30
Excalidraw Bot
c8d1cd6cc3 New translations en.json (Italian) 2024-01-06 20:07:42 +01:00
Excalidraw Bot
558e9382ae Auto commit: Calculate translation coverage 2024-01-06 10:54:10 +00:00
Excalidraw Bot
1ec0b25c3d New translations en.json (Romanian) 2024-01-06 11:53:58 +01:00
Excalidraw Bot
4d08a6568b Auto commit: Calculate translation coverage 2024-01-06 04:35:47 +00:00
Excalidraw Bot
2ef35fd2f8 New translations en.json (Hindi) 2024-01-06 05:35:33 +01:00
Excalidraw Bot
cc44844029 New translations en.json (Marathi) 2024-01-06 05:35:32 +01:00
Excalidraw Bot
970903992a Auto commit: Calculate translation coverage 2024-01-05 18:37:25 +00:00
Excalidraw Bot
ac160b6a18 New translations en.json (Slovak) 2024-01-05 19:37:11 +01:00
Excalidraw Bot
535a99a12f Auto commit: Calculate translation coverage 2024-01-05 08:09:35 +00:00
Excalidraw Bot
6415432eb5 New translations en.json (Chinese Simplified) 2024-01-05 09:09:23 +01:00
Excalidraw Bot
30e9692158 Auto commit: Calculate translation coverage 2024-01-04 21:12:51 +00:00
Excalidraw Bot
148bce498e New translations en.json (Portuguese) 2024-01-04 22:12:39 +01:00
Excalidraw Bot
9455b0942b Auto commit: Calculate translation coverage 2024-01-04 20:02:43 +00:00
Excalidraw Bot
a279bbb5fd New translations en.json (Portuguese, Brazilian) 2024-01-04 21:02:30 +01:00
Excalidraw Bot
3843e24ba0 New translations en.json (Portuguese) 2024-01-04 21:02:28 +01:00
Excalidraw Bot
91ada50547 Auto commit: Calculate translation coverage 2024-01-04 18:12:59 +00:00
Excalidraw Bot
c969c730a5 New translations en.json (Chinese Traditional) 2024-01-04 19:12:47 +01:00
Excalidraw Bot
560cd5ec32 New translations en.json (Russian) 2024-01-04 19:12:46 +01:00
Excalidraw Bot
186c3755e9 New translations en.json (Portuguese) 2024-01-04 19:12:45 +01:00
Excalidraw Bot
a8113203d4 New translations en.json (German) 2024-01-04 19:12:44 +01:00
David Luzar
8b993d409e feat: render embeds lazily (#7519) 2024-01-04 19:03:04 +01:00
Excalidraw Bot
2e1da33411 Auto commit: Calculate translation coverage 2024-01-04 16:21:40 +00:00
Excalidraw Bot
053dce7b8b New translations en.json (Swedish) 2024-01-04 17:21:27 +01:00
Excalidraw Bot
4941ffdcae New translations en.json (Slovenian) 2024-01-04 17:21:26 +01:00
Excalidraw Bot
845d519fc9 New translations en.json (Portuguese) 2024-01-04 17:21:25 +01:00
Excalidraw Bot
cb59638222 Auto commit: Calculate translation coverage 2024-01-04 14:48:12 +00:00
Excalidraw Bot
1cf00f8f28 New translations en.json (Karakalpak) 2024-01-04 15:46:16 +01:00
Excalidraw Bot
3138e75dfe New translations en.json (Kabyle) 2024-01-04 15:46:15 +01:00
Excalidraw Bot
c0fd470198 New translations en.json (Occitan) 2024-01-04 15:46:14 +01:00
Excalidraw Bot
44dd859a11 New translations en.json (Norwegian Bokmal) 2024-01-04 15:46:13 +01:00
Excalidraw Bot
fb207ad1d4 New translations en.json (Sinhala) 2024-01-04 15:46:11 +01:00
Excalidraw Bot
238324505f New translations en.json (Chinese Traditional, Hong Kong) 2024-01-04 15:46:09 +01:00
Excalidraw Bot
9685ac01a1 New translations en.json (Burmese) 2024-01-04 15:46:08 +01:00
Excalidraw Bot
ebf18e369b New translations en.json (Hindi) 2024-01-04 15:46:07 +01:00
Excalidraw Bot
d1663324be New translations en.json (Azerbaijani) 2024-01-04 15:46:06 +01:00
Excalidraw Bot
37e8eb1211 New translations en.json (Latvian) 2024-01-04 15:46:05 +01:00
Excalidraw Bot
d27063eea4 New translations en.json (Kazakh) 2024-01-04 15:46:04 +01:00
Excalidraw Bot
77a89d12f2 New translations en.json (Norwegian Nynorsk) 2024-01-04 15:46:03 +01:00
Excalidraw Bot
e66d7717ab New translations en.json (Thai) 2024-01-04 15:46:01 +01:00
Excalidraw Bot
828772e4f2 New translations en.json (Marathi) 2024-01-04 15:46:00 +01:00
Excalidraw Bot
087cfdfb9f New translations en.json (Bengali) 2024-01-04 15:45:59 +01:00
Excalidraw Bot
77a7cca80c New translations en.json (Tamil) 2024-01-04 15:45:58 +01:00
Excalidraw Bot
d24c875aeb New translations en.json (Khmer) 2024-01-04 15:45:57 +01:00
Excalidraw Bot
6c974d033b New translations en.json (Indonesian) 2024-01-04 15:45:56 +01:00
Excalidraw Bot
5ee8fd7448 New translations en.json (Portuguese, Brazilian) 2024-01-04 15:45:55 +01:00
Excalidraw Bot
23352dd668 New translations en.json (Galician) 2024-01-04 15:45:54 +01:00
Excalidraw Bot
60524a49be New translations en.json (Vietnamese) 2024-01-04 15:45:53 +01:00
Excalidraw Bot
76665cc7a1 New translations en.json (Chinese Traditional) 2024-01-04 15:45:52 +01:00
Excalidraw Bot
6cd8bbf5e2 New translations en.json (Ukrainian) 2024-01-04 15:45:51 +01:00
Excalidraw Bot
8602bb66ab New translations en.json (Turkish) 2024-01-04 15:45:50 +01:00
Excalidraw Bot
20d40522da New translations en.json (Swedish) 2024-01-04 15:45:48 +01:00
Excalidraw Bot
44d4e069e4 New translations en.json (Slovenian) 2024-01-04 15:45:47 +01:00
Excalidraw Bot
309790a707 New translations en.json (Russian) 2024-01-04 15:45:46 +01:00
Excalidraw Bot
8a17d6287c New translations en.json (Portuguese) 2024-01-04 15:45:45 +01:00
Excalidraw Bot
bea2193b82 New translations en.json (Polish) 2024-01-04 15:45:44 +01:00
Excalidraw Bot
3819b41865 New translations en.json (Punjabi) 2024-01-04 15:45:42 +01:00
Excalidraw Bot
52e7bab8e6 New translations en.json (Dutch) 2024-01-04 15:45:42 +01:00
Excalidraw Bot
7916134430 New translations en.json (Lithuanian) 2024-01-04 15:45:40 +01:00
Excalidraw Bot
e1944b4d45 New translations en.json (Kurdish) 2024-01-04 15:45:39 +01:00
Excalidraw Bot
7fe05e26d6 New translations en.json (Korean) 2024-01-04 15:45:38 +01:00
Excalidraw Bot
a654815139 New translations en.json (Japanese) 2024-01-04 15:45:37 +01:00
Excalidraw Bot
d7c69316f7 New translations en.json (Hungarian) 2024-01-04 15:45:35 +01:00
Excalidraw Bot
a22d237f2a New translations en.json (Hebrew) 2024-01-04 15:45:34 +01:00
Excalidraw Bot
f92acf6481 New translations en.json (Finnish) 2024-01-04 15:45:33 +01:00
Excalidraw Bot
c7adb02973 New translations en.json (Basque) 2024-01-04 15:45:32 +01:00
Excalidraw Bot
ce0ed0bdd3 New translations en.json (Greek) 2024-01-04 15:45:31 +01:00
Excalidraw Bot
3b51f9711c New translations en.json (German) 2024-01-04 15:45:30 +01:00
Excalidraw Bot
ca0f7f417b New translations en.json (Danish) 2024-01-04 15:45:29 +01:00
Excalidraw Bot
9f59e2080d New translations en.json (Czech) 2024-01-04 15:45:28 +01:00
Excalidraw Bot
1e6778ec11 New translations en.json (Catalan) 2024-01-04 15:45:27 +01:00
Excalidraw Bot
a1cdec0995 New translations en.json (Bulgarian) 2024-01-04 15:45:26 +01:00
Excalidraw Bot
6593913c7e New translations en.json (Arabic) 2024-01-04 15:45:25 +01:00
Excalidraw Bot
9fb3f7d223 New translations en.json (Spanish) 2024-01-04 15:45:24 +01:00
Excalidraw Bot
8a43bc35d7 New translations en.json (Romanian) 2024-01-04 15:45:23 +01:00
Excalidraw Bot
2e65fb9441 New translations en.json (French) 2024-01-04 15:45:22 +01:00
Excalidraw Bot
f0326c4a82 New translations en.json (Italian) 2024-01-04 15:45:21 +01:00
Excalidraw Bot
1deb577b6e New translations en.json (Persian) 2024-01-04 15:45:20 +01:00
Excalidraw Bot
60c59a9575 New translations en.json (Slovak) 2024-01-04 15:45:19 +01:00
Excalidraw Bot
fddc299b60 New translations en.json (Chinese Simplified) 2024-01-04 15:45:18 +01:00
David Luzar
1cb350b2aa feat: update X brand logo & tweak labels (#7518) 2024-01-04 14:57:31 +01:00
David Luzar
43ccc875fb feat: support multi-embed pasting & x.com domain (#7516) 2024-01-04 13:27:52 +01:00
Aakansha Doshi
4249b7dec8 chore: add version for excalidraw-app workspace (#7514) 2024-01-04 13:53:19 +05:30
Aakansha Doshi
49f15c736b chore: remove unused files (#7509)
chore remove unused files
2024-01-03 16:25:36 +05:30
Aakansha Doshi
a8064ba3ee build: Welcome ESM and Bye Bye UMD (#7441)
* build: Welcome ESM and Bye Bye UMD

* remove package

* create unbundled esm build

* update script for example

* fix typo

* dummy commit

* update autorelease script to build esm

* revert dummy commit

* move react, react-dom and testing library to dev dependencies

* remove entry.js, publicPath and yarn install:deps script

* fix

* upgrade esbuild to fix glob import error for locales

* remove webpack chunk names as thats not needed anymore

* marking the code sideeffects free

* make the library tree-shakeable and move fonts to fonts directory

* allow side effects for css, scss files

* remove tree-shaking

* comment code for tree shaking

* move to vite for example

* bye bye webpack

* ignore ts

* separate build and output dir

* use esbuild for creating bundle for example

* update output dir

* lint

* create browser dev build with source maps and prod with minification

* add dev and prod builds for bundler

* lint

* update script

* remove await

* load prod build

* create minified build in dist

* prod and dev builds using export field

* remove import.meta

* dummy

* define import.meta prod and dev

* fix

* export types

* add types field

* typo

* lint

* Update scripts/buildPackage.js

* move types inside export

* newline
2024-01-01 20:18:44 +05:30
David Luzar
e6c3c06c2e feat: support pen erasing (#7496) 2024-01-01 13:27:03 +01:00
Excalidraw Bot
892fe1917e Auto commit: Calculate translation coverage 2023-12-30 16:18:06 +00:00
Excalidraw Bot
7979b5e11c New translations en.json (French) 2023-12-30 17:17:53 +01:00
David Luzar
d19b51d4f8 fix: drawing-tablet stylus touch events being prevented (#7494) 2023-12-30 15:00:12 +01:00
David Luzar
c72e853c85 refactor: editor events sub/unsub refactor (#7483) 2023-12-30 11:12:38 +01:00
Excalidraw Bot
d5fba1e199 Auto commit: Calculate translation coverage 2023-12-23 13:08:01 +00:00
Excalidraw Bot
4629c88279 New translations en.json (Italian) 2023-12-23 14:07:47 +01:00
Excalidraw Bot
381809e1bd Auto commit: Calculate translation coverage 2023-12-23 10:34:22 +00:00
Excalidraw Bot
a06c103aa7 New translations en.json (Persian) 2023-12-23 11:34:06 +01:00
Excalidraw Bot
ae43f480d6 Auto commit: Calculate translation coverage 2023-12-22 10:38:58 +00:00
Excalidraw Bot
b7535f0b0e New translations en.json (Slovak) 2023-12-22 11:38:44 +01:00
Excalidraw Bot
9d7dd3afef New translations en.json (Slovak) 2023-12-22 09:45:33 +01:00
Excalidraw Bot
6e70165e8c Auto commit: Calculate translation coverage 2023-12-22 01:52:18 +00:00
Excalidraw Bot
b9759d2c77 New translations en.json (Chinese Simplified) 2023-12-22 02:52:03 +01:00
Excalidraw Bot
1cb3feec51 Auto commit: Calculate translation coverage 2023-12-20 17:36:37 +00:00
Excalidraw Bot
7c0f1f42f6 New translations en.json (Chinese Traditional) 2023-12-20 18:36:23 +01:00
Excalidraw Bot
4b9dae1986 Auto commit: Calculate translation coverage 2023-12-20 11:17:25 +00:00
Excalidraw Bot
8e13821456 New translations en.json (Hindi) 2023-12-20 12:17:11 +01:00
Excalidraw Bot
9ae10b66ab New translations en.json (Marathi) 2023-12-20 12:17:10 +01:00
Excalidraw Bot
f77fcc28d9 Auto commit: Calculate translation coverage 2023-12-20 06:13:39 +00:00
Excalidraw Bot
20a6bdb55c New translations en.json (Korean) 2023-12-20 07:13:22 +01:00
zsviczian
5f40a4cad4 fix: missing cross-env from build:umd in package.json (#7460) 2023-12-19 00:02:03 +01:00
Excalidraw Bot
7f4bcbe853 Auto commit: Calculate translation coverage 2023-12-18 20:50:20 +00:00
Excalidraw Bot
a7e2e053f3 New translations en.json (Russian) 2023-12-18 21:50:07 +01:00
Excalidraw Bot
c870c7adab New translations en.json (German) 2023-12-18 21:50:06 +01:00
Excalidraw Bot
9075584a3a New translations en.json (Spanish) 2023-12-18 21:50:05 +01:00
David Luzar
d91c98b82e fix: incorrect types in ActionNavigate (#7462) 2023-12-18 21:14:30 +01:00
Excalidraw Bot
00f35af572 Auto commit: Calculate translation coverage 2023-12-18 18:13:16 +00:00
Excalidraw Bot
24d5be9e8c New translations en.json (Romanian) 2023-12-18 19:13:02 +01:00
David Luzar
57ea4e61d1 fix: mixing clientId & socketId in UserList (#7461) 2023-12-18 18:21:57 +01:00
Excalidraw Bot
7b671d0d74 Auto commit: Calculate translation coverage 2023-12-18 17:05:33 +00:00
Excalidraw Bot
6ad3077c69 New translations en.json (Swedish) 2023-12-18 18:05:20 +01:00
Excalidraw Bot
4f1d578b2f New translations en.json (Slovenian) 2023-12-18 18:05:18 +01:00
Excalidraw Bot
685eb8cb50 Auto commit: Calculate translation coverage 2023-12-18 16:00:56 +00:00
Excalidraw Bot
998331f937 New translations en.json (Karakalpak) 2023-12-18 16:57:33 +01:00
Excalidraw Bot
fdd3ea29e0 New translations en.json (Kabyle) 2023-12-18 16:57:31 +01:00
Excalidraw Bot
f25781db38 New translations en.json (Occitan) 2023-12-18 16:57:30 +01:00
Excalidraw Bot
8bde613823 New translations en.json (Norwegian Bokmal) 2023-12-18 16:57:29 +01:00
Excalidraw Bot
e9db8195e0 New translations en.json (Sinhala) 2023-12-18 16:57:28 +01:00
Excalidraw Bot
944f823847 New translations en.json (Chinese Traditional, Hong Kong) 2023-12-18 16:57:27 +01:00
Excalidraw Bot
377243b07f New translations en.json (Burmese) 2023-12-18 16:57:26 +01:00
Excalidraw Bot
c86c73dd8f New translations en.json (Hindi) 2023-12-18 16:57:25 +01:00
Excalidraw Bot
4f453600db New translations en.json (Azerbaijani) 2023-12-18 16:57:24 +01:00
Excalidraw Bot
4ff1dbc8b1 New translations en.json (Latvian) 2023-12-18 16:57:23 +01:00
Excalidraw Bot
18463b79b3 New translations en.json (Kazakh) 2023-12-18 16:57:22 +01:00
Excalidraw Bot
9e19d2d166 New translations en.json (Norwegian Nynorsk) 2023-12-18 16:57:21 +01:00
Excalidraw Bot
17e9de9a53 New translations en.json (Thai) 2023-12-18 16:57:19 +01:00
Excalidraw Bot
4a0f4fc4ea New translations en.json (Marathi) 2023-12-18 16:57:18 +01:00
Excalidraw Bot
124d7a388f New translations en.json (Bengali) 2023-12-18 16:57:17 +01:00
Excalidraw Bot
0b34294156 New translations en.json (Tamil) 2023-12-18 16:57:16 +01:00
Excalidraw Bot
d296b12f0e New translations en.json (Khmer) 2023-12-18 16:57:15 +01:00
Excalidraw Bot
2d62da8dfe New translations en.json (Persian) 2023-12-18 16:57:14 +01:00
Excalidraw Bot
6115b9a808 New translations en.json (Indonesian) 2023-12-18 16:57:13 +01:00
Excalidraw Bot
e034410a91 New translations en.json (Portuguese, Brazilian) 2023-12-18 16:57:12 +01:00
Excalidraw Bot
800a609b4f New translations en.json (Galician) 2023-12-18 16:57:10 +01:00
Excalidraw Bot
ce69926f8a New translations en.json (Vietnamese) 2023-12-18 16:57:09 +01:00
Excalidraw Bot
e38a33b7b4 New translations en.json (Chinese Traditional) 2023-12-18 16:57:08 +01:00
Excalidraw Bot
95ab1256ba New translations en.json (Chinese Simplified) 2023-12-18 16:57:07 +01:00
Excalidraw Bot
f7a3dbd9f2 New translations en.json (Ukrainian) 2023-12-18 16:57:06 +01:00
Excalidraw Bot
4552db4fa1 New translations en.json (Turkish) 2023-12-18 16:57:05 +01:00
Excalidraw Bot
a33bb248a4 New translations en.json (Swedish) 2023-12-18 16:57:04 +01:00
Excalidraw Bot
2df55f0be7 New translations en.json (Slovenian) 2023-12-18 16:57:03 +01:00
Excalidraw Bot
a0094fce80 New translations en.json (Slovak) 2023-12-18 16:57:02 +01:00
Excalidraw Bot
72a525063a New translations en.json (Russian) 2023-12-18 16:57:01 +01:00
Excalidraw Bot
0484b8db51 New translations en.json (Portuguese) 2023-12-18 16:56:59 +01:00
Excalidraw Bot
c63781abe3 New translations en.json (Polish) 2023-12-18 16:56:58 +01:00
Excalidraw Bot
b496e68bf9 New translations en.json (Punjabi) 2023-12-18 16:56:57 +01:00
Excalidraw Bot
d0df605151 New translations en.json (Dutch) 2023-12-18 16:56:56 +01:00
Excalidraw Bot
0796621702 New translations en.json (Lithuanian) 2023-12-18 16:56:55 +01:00
Excalidraw Bot
d883fa7cc0 New translations en.json (Kurdish) 2023-12-18 16:56:54 +01:00
Excalidraw Bot
bf68b8b3b2 New translations en.json (Korean) 2023-12-18 16:56:53 +01:00
Excalidraw Bot
8136962237 New translations en.json (Japanese) 2023-12-18 16:56:52 +01:00
Excalidraw Bot
b8a62be016 New translations en.json (Italian) 2023-12-18 16:56:51 +01:00
Excalidraw Bot
f86bc0fab9 New translations en.json (Hungarian) 2023-12-18 16:56:50 +01:00
Excalidraw Bot
422941f260 New translations en.json (Hebrew) 2023-12-18 16:56:49 +01:00
Excalidraw Bot
b839775904 New translations en.json (Finnish) 2023-12-18 16:56:47 +01:00
Excalidraw Bot
69de41c981 New translations en.json (Basque) 2023-12-18 16:56:46 +01:00
Excalidraw Bot
037dfadbc2 New translations en.json (Greek) 2023-12-18 16:56:45 +01:00
Excalidraw Bot
d6a512f05b New translations en.json (German) 2023-12-18 16:56:44 +01:00
Excalidraw Bot
c2f83885cb New translations en.json (Danish) 2023-12-18 16:56:43 +01:00
Excalidraw Bot
4c8f41f312 New translations en.json (Czech) 2023-12-18 16:56:42 +01:00
Excalidraw Bot
93d66a7958 New translations en.json (Catalan) 2023-12-18 16:56:41 +01:00
Excalidraw Bot
8dce1413b9 New translations en.json (Bulgarian) 2023-12-18 16:56:39 +01:00
Excalidraw Bot
e4fdab7c96 New translations en.json (Arabic) 2023-12-18 16:56:38 +01:00
Excalidraw Bot
2a748aa76a New translations en.json (Spanish) 2023-12-18 16:56:37 +01:00
Excalidraw Bot
d8049f3843 New translations en.json (French) 2023-12-18 16:56:36 +01:00
Excalidraw Bot
d9edc2e30d New translations en.json (Romanian) 2023-12-18 16:56:35 +01:00
David Luzar
0808532b49 fix: follow mode collaborator status indicator (#7459) 2023-12-18 16:14:25 +01:00
Lynda Lin
2a0fe2584e fix: empty snapLines arrays would cause re-render (#7454)
Co-authored-by: Lynda Lin <lynda.lin@optoma.com>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-18 12:42:17 +00:00
Adithyan
7bd6496854 refactor: Fix Typo (#7445) 2023-12-16 18:23:11 +00:00
Jason Praful
537f6e7f68 docs: add steps for local development (#7449)
* docs: add steps for local development #7434

* docs: minor tweaks

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-16 19:18:35 +01:00
David Luzar
6dfa89e846 fix: emitted visible scene bounds not accounting for offsets (#7450) 2023-12-16 17:32:54 +01:00
David Luzar
561e919a2e fix: import Socket as type (#7446) 2023-12-16 11:15:04 +01:00
David Luzar
20e3acf7a6 feat: bump socket.io-client & collab tweaks (#7444) 2023-12-16 00:23:59 +01:00
David Luzar
2c0929e537 fix: follow-mode tweaks (#7443) 2023-12-15 15:16:25 +01:00
Barnabás Molnár
aad8ab0123 feat: follow mode (#6848)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-12-15 00:07:11 +01:00
Aakansha Doshi
88a2b286c7 feat: move utils to utils package and make @excalidraw/utils a workspace (#7432)
* feat: move utils to utils package and make @excalidraw/utils a workspace

* remove esm and update types path

* remove esm script

* fix package.json and yarn.lock

* update path

* fix

* fix lint and test
2023-12-13 21:51:27 +05:30
Excalidraw Bot
f8c48e44e0 Auto commit: Calculate translation coverage 2023-12-13 11:32:16 +00:00
Excalidraw Bot
f37bc01fe7 New translations en.json (Polish) 2023-12-13 12:32:03 +01:00
Excalidraw Bot
ae460c569a Auto commit: Calculate translation coverage 2023-12-13 10:07:05 +00:00
Excalidraw Bot
1e535dd779 New translations en.json (Hindi) 2023-12-13 11:06:51 +01:00
Excalidraw Bot
ea8f5a124e New translations en.json (Marathi) 2023-12-13 11:06:49 +01:00
Excalidraw Bot
93ad17baa7 Auto commit: Calculate translation coverage 2023-12-13 06:16:20 +00:00
Excalidraw Bot
b933ddb315 New translations en.json (Marathi) 2023-12-13 07:16:04 +01:00
Excalidraw Bot
e010d12752 New translations en.json (Portuguese, Brazilian) 2023-12-13 07:16:03 +01:00
Excalidraw Bot
3e4c51ebf9 Auto commit: Calculate translation coverage 2023-12-13 05:08:26 +00:00
Excalidraw Bot
58df7cfe70 New translations en.json (Marathi) 2023-12-13 06:08:08 +01:00
Excalidraw Bot
b5ec37b698 Auto commit: Calculate translation coverage 2023-12-12 18:31:08 +00:00
Excalidraw Bot
624f17bd3c New translations en.json (German) 2023-12-12 19:30:51 +01:00
Excalidraw Bot
744525dcaf Auto commit: Calculate translation coverage 2023-12-12 15:18:00 +00:00
Excalidraw Bot
05190598bc New translations en.json (Spanish) 2023-12-12 16:17:43 +01:00
Excalidraw Bot
da6f52a155 Auto commit: Calculate translation coverage 2023-12-12 14:11:43 +00:00
Excalidraw Bot
e5d639270e New translations en.json (Slovenian) 2023-12-12 15:11:28 +01:00
Excalidraw Bot
11da1e5b30 New translations en.json (Spanish) 2023-12-12 15:11:27 +01:00
Excalidraw Bot
7cfc7c7811 Auto commit: Calculate translation coverage 2023-12-12 13:02:31 +00:00
Excalidraw Bot
cf6af5e70d New translations en.json (Chinese Traditional) 2023-12-12 14:02:16 +01:00
Excalidraw Bot
898dfff1a0 Auto commit: Calculate translation coverage 2023-12-12 11:29:53 +00:00
Excalidraw Bot
2660e4edde New translations en.json (Karakalpak) 2023-12-12 12:29:43 +01:00
Excalidraw Bot
8e05ff0c32 New translations en.json (Occitan) 2023-12-12 12:29:41 +01:00
Excalidraw Bot
c4cb94bff8 New translations en.json (Norwegian Bokmal) 2023-12-12 12:29:40 +01:00
Excalidraw Bot
10ee9c4019 New translations en.json (Hindi) 2023-12-12 12:29:37 +01:00
Excalidraw Bot
042bcf0638 New translations en.json (Azerbaijani) 2023-12-12 12:29:36 +01:00
Excalidraw Bot
8c30adaf10 New translations en.json (Norwegian Nynorsk) 2023-12-12 12:29:33 +01:00
Excalidraw Bot
2fcd49791e New translations en.json (Thai) 2023-12-12 12:29:32 +01:00
Excalidraw Bot
ae0c96b66c New translations en.json (Marathi) 2023-12-12 12:29:31 +01:00
Excalidraw Bot
c195bb0739 New translations en.json (Tamil) 2023-12-12 12:29:29 +01:00
Excalidraw Bot
6de5305e72 New translations en.json (Khmer) 2023-12-12 12:29:28 +01:00
Excalidraw Bot
ca1d426fc0 New translations en.json (Persian) 2023-12-12 12:29:27 +01:00
Excalidraw Bot
4fd311364a New translations en.json (Indonesian) 2023-12-12 12:29:26 +01:00
Excalidraw Bot
9d6180e2fd New translations en.json (Portuguese, Brazilian) 2023-12-12 12:29:25 +01:00
Excalidraw Bot
eeeb7e4ed9 New translations en.json (Galician) 2023-12-12 12:29:24 +01:00
Excalidraw Bot
9c248e8ae9 New translations en.json (Vietnamese) 2023-12-12 12:29:23 +01:00
Excalidraw Bot
d579328746 New translations en.json (Chinese Traditional) 2023-12-12 12:29:22 +01:00
Excalidraw Bot
3b3cfc391e New translations en.json (Chinese Simplified) 2023-12-12 12:29:21 +01:00
Excalidraw Bot
222fa328ba New translations en.json (Ukrainian) 2023-12-12 12:29:20 +01:00
Excalidraw Bot
a83498fc61 New translations en.json (Turkish) 2023-12-12 12:29:19 +01:00
Excalidraw Bot
0bd531b612 New translations en.json (Swedish) 2023-12-12 12:29:18 +01:00
Excalidraw Bot
b9b35833d3 New translations en.json (Slovenian) 2023-12-12 12:29:16 +01:00
Excalidraw Bot
eac2a23d72 New translations en.json (Slovak) 2023-12-12 12:29:15 +01:00
Excalidraw Bot
641a766607 New translations en.json (Russian) 2023-12-12 12:29:14 +01:00
Excalidraw Bot
bf38bd6620 New translations en.json (Portuguese) 2023-12-12 12:29:13 +01:00
Excalidraw Bot
775e551c3d New translations en.json (Polish) 2023-12-12 12:29:12 +01:00
Excalidraw Bot
909cc53c3a New translations en.json (Punjabi) 2023-12-12 12:29:11 +01:00
Excalidraw Bot
99e5542f03 New translations en.json (Dutch) 2023-12-12 12:29:10 +01:00
Excalidraw Bot
96b8340210 New translations en.json (Kurdish) 2023-12-12 12:29:08 +01:00
Excalidraw Bot
f92d025434 New translations en.json (Korean) 2023-12-12 12:29:07 +01:00
Excalidraw Bot
bbbed516f2 New translations en.json (Japanese) 2023-12-12 12:29:06 +01:00
Excalidraw Bot
c86a878a75 New translations en.json (Italian) 2023-12-12 12:29:05 +01:00
Excalidraw Bot
6676f24c4f New translations en.json (Hungarian) 2023-12-12 12:29:04 +01:00
Excalidraw Bot
e2e336bd95 New translations en.json (Basque) 2023-12-12 12:29:01 +01:00
Excalidraw Bot
c5ec66e585 New translations en.json (Greek) 2023-12-12 12:29:00 +01:00
Excalidraw Bot
a0c7aae672 New translations en.json (German) 2023-12-12 12:28:59 +01:00
Excalidraw Bot
95c8418dee New translations en.json (Danish) 2023-12-12 12:28:58 +01:00
Excalidraw Bot
21f5934e44 New translations en.json (Czech) 2023-12-12 12:28:57 +01:00
Excalidraw Bot
d6e2936bf8 New translations en.json (Catalan) 2023-12-12 12:28:56 +01:00
Excalidraw Bot
0aa1b62108 New translations en.json (Bulgarian) 2023-12-12 12:28:55 +01:00
Excalidraw Bot
c7c41155f6 New translations en.json (Arabic) 2023-12-12 12:28:54 +01:00
Excalidraw Bot
492a643506 New translations en.json (Spanish) 2023-12-12 12:28:52 +01:00
Excalidraw Bot
1cc8ad6ed9 New translations en.json (French) 2023-12-12 12:28:51 +01:00
Excalidraw Bot
8f57c10d9b New translations en.json (Romanian) 2023-12-12 12:28:50 +01:00
Excalidraw Bot
b635b10b59 chore: Update translations from Crowdin (#7176)
* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (Marathi)

* New translations en.json (Hindi)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* New translations en.json (Thai)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Russian)

* Auto commit: Calculate translation coverage

* New translations en.json (Polish)

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* New translations en.json (Catalan)

* Auto commit: Calculate translation coverage

* New translations en.json (Basque)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Arabic)

* New translations en.json (Thai)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (Spanish)

* Auto commit: Calculate translation coverage

* New translations en.json (Slovenian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Traditional)

* Auto commit: Calculate translation coverage

* New translations en.json (Swedish)

* Auto commit: Calculate translation coverage

* New translations en.json (French)

* Auto commit: Calculate translation coverage

* New translations en.json (German)

* Auto commit: Calculate translation coverage

* New translations en.json (Danish)

* Auto commit: Calculate translation coverage

* New translations en.json (Italian)

* Auto commit: Calculate translation coverage

* New translations en.json (Chinese Simplified)

* Auto commit: Calculate translation coverage

* New translations en.json (Korean)

* Auto commit: Calculate translation coverage

* New translations en.json (Polish)

* New translations en.json (Slovak)

* Auto commit: Calculate translation coverage

* New translations en.json (Karakalpak)

* Auto commit: Calculate translation coverage

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Bulgarian)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Basque)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Kurdish)

* New translations en.json (Lithuanian)

* New translations en.json (Dutch)

* New translations en.json (Punjabi)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Slovak)

* New translations en.json (Slovenian)

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Galician)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Indonesian)

* New translations en.json (Persian)

* New translations en.json (Khmer)

* New translations en.json (Tamil)

* New translations en.json (Bengali)

* New translations en.json (Marathi)

* New translations en.json (Thai)

* New translations en.json (Norwegian Nynorsk)

* New translations en.json (Kazakh)

* New translations en.json (Latvian)

* New translations en.json (Azerbaijani)

* New translations en.json (Hindi)

* New translations en.json (Burmese)

* New translations en.json (Chinese Traditional, Hong Kong)

* New translations en.json (Sinhala)

* New translations en.json (Norwegian Bokmal)

* New translations en.json (Occitan)

* New translations en.json (Kabyle)

* New translations en.json (Karakalpak)

* New translations en.json (Swedish)

* New translations en.json (Romanian)

* remove packages

---------

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-12-12 16:56:22 +05:30
Aakansha Doshi
7ebda02b81 fix: update path of files in docs (#7428)
* fix: update path of files in docs

* remove root yarn install in size limit

* add vercel.json in dev-docs

* update config

* fix lint

* indent

* revert changelog and readme
2023-12-12 14:28:34 +05:30
Aakansha Doshi
d6cd8b78f1 build: decouple package deps and introduce yarn workspaces (#7415)
* feat: decouple package deps and introduce yarn workspaces

* update root directory

* fix

* fix scripts

* fix lint

* update path in scripts

* remove yarn.lock files from packages

* ignore workspace

* dummy

* dummy

* remove comment check

* revert workflow changes

* ignore ws when installing gh actions

* remove log

* update path

* fix

* fix typo
2023-12-12 11:32:51 +05:30
Aakansha Doshi
b7d7ccc929 fix: env variable for text-to-diagram and use frozen lock file when install deps in excalidraw-app (#7409) 2023-12-07 19:32:19 +05:30
Aakansha Doshi
f14ad61bd0 build: move build process and excalidraw-app dependencies in its own package.json (#7021)
* build: move build process and excalidraw-app dependencies in its own package.json

* fix

* fix public path

* move bug-issue-template to excalidraw-app

* make env vars accessible in excalidraw app

* update build script

* install when building

* add ts ignore

* fix build-version script

* update config in vercel.json

* add vercel config for example

* fix vercel config

* update install script in vercel

* update install script in lint.yml

* update install script in test workflows

* push locales to locales folder pwa

* add favicons to manifest

* move react to peer deps in editor

* fix ts

* Enable vite intellisense

* add global.d.ts for excalidraw-app

* remove console.log

* remove react, react-dom and vite from excalidraw-app deps

* increase size limit
2023-12-07 16:39:11 +05:30
Aakansha Doshi
8963baf5ad chore: upgrade to vite 5.x and vitest 1.x (#7407)
* chore: upgrade to vite 5.x and vitest 1.x

* fix coverage

* move to ESM for vite config

* use ESM for vitest
2023-12-07 15:30:08 +05:30
Aakansha Doshi
557add5bf7 feat: Support Mermaid Class diagrams 🥳 (#7381)
* feat: support mermaid class diagrams

* upgrade mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* add sequence diagrams in supported chart types

* upgrade mermaid-to-excalidraw

* update i18n
2023-12-06 21:31:54 +05:30
David Luzar
b9cfbc2077 feat: add support for more UML arrowheads (#7391) 2023-12-06 16:00:00 +01:00
dependabot[bot]
a04cc707c3 build(deps-dev): bump vite from 4.4.2 to 4.4.12 (#7393)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.4.2 to 4.4.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.4.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.4.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-06 15:31:44 +05:30
Vaibhav Shukla
72ea8022bf docs: changelog instruction removed from docs (#7395)
changelog instruction removed from docs
2023-12-06 11:36:39 +05:30
David Luzar
4bdeaf999b feat: TTD dialog UI tweaks (#7384) 2023-12-04 17:50:30 +01:00
Aakansha Doshi
42d8c5a040 chore: update changelog and package.json for v0.17.1 (#7351) 2023-11-28 19:12:39 +05:30
Aakansha Doshi
f299514e44 fix: umd build so it can be used in browser (#7349)
* fix: umd build so it can be used in browser

* fix lint

* increase size limit

* update changelog

* use json.stringify for env preact variable so its accessible as string

* update changelog
2023-11-28 18:11:16 +05:30
David Luzar
dd220bcaea feat: TTD dialog tweaks (#7346)
* tweaks to TTD dialog ~ prepping for settings dialog

* tweaks to ttd parsing & error logging
2023-11-27 16:03:03 +01:00
David Luzar
fe75f29c15 fix: disable caching bounds for arrow labels (#7343) 2023-11-25 23:32:05 +01:00
Barnabás Molnár
14845a343b feat: text-to-diagram (#7325)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2023-11-25 21:11:03 +00:00
David Luzar
dd8a7d41e2 fix: bounds cached prematurely resulting in incorrectly rendered labels (#7339) 2023-11-24 19:55:56 +01:00
David Luzar
fda5c6fdf7 fix: t2c settings dialog spacing for apps that use CSS resets (#7337) 2023-11-24 16:32:00 +01:00
David Luzar
3d1631f375 feat: d2c tweaks (#7336) 2023-11-24 14:02:11 +01:00
David Luzar
c7ee46e7f8 feat: wireframe-to-code (#7334) 2023-11-23 23:07:53 +01:00
DanielJGeiger
d1e4421823 feat: Expose ActionManager.registerAction through ExcalidrawImperativeAPI (#6995)
* feat: Expose `ActionManager` through `ExcalidrawImperativeAPI`

* Only expose `registerAction` instead of `ActionManager`
2023-11-22 15:22:49 -06:00
Barnabás Molnár
7c9cf30909 fix: make zoomToFit fitToViewport account for sidebar (#7298) 2023-11-17 15:56:19 +01:00
David Luzar
1e37dbd60e feat: change frame resizing behavior (#7307) 2023-11-17 14:37:43 +01:00
David Luzar
f8d5c2a1b6 build: allow a range of major node versions (#7306) 2023-11-17 14:23:19 +01:00
Aakansha Doshi
23b24ea5c3 build: use caret for specifying node version to avoid major upgrades automatically (#7297) 2023-11-16 16:18:38 +05:30
698 changed files with 46614 additions and 23501 deletions

View File

@@ -6,6 +6,6 @@
!.prettierrc
!package.json
!public/
!src/
!packages/
!tsconfig.json
!yarn.lock

View File

@@ -7,12 +7,11 @@ VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfu
# collaboration WebSocket server (https://github.com/excalidraw/excalidraw-room)
VITE_APP_WS_SERVER_URL=http://localhost:3002
# set this only if using the collaboration workflow we use on excalidraw.com
VITE_APP_PORTAL_URL=
VITE_APP_PLUS_LP=https://plus.excalidraw.com
VITE_APP_PLUS_APP=https://app.excalidraw.com
VITE_APP_AI_BACKEND=http://localhost:3015
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
# put these in your .env.local, or make sure you don't commit!

View File

@@ -4,14 +4,13 @@ VITE_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
VITE_APP_PORTAL_URL=https://portal.excalidraw.com
VITE_APP_PLUS_LP=https://plus.excalidraw.com
VITE_APP_PLUS_APP=https://app.excalidraw.com
# Fill to set socket server URL used for collaboration.
# Meant for forks only: excalidraw.com uses custom VITE_APP_PORTAL_URL flow
VITE_APP_WS_SERVER_URL=
VITE_APP_AI_BACKEND=https://oss-ai.excalidraw.com
# socket server URL used for collaboration
VITE_APP_WS_SERVER_URL=https://oss-collab.excalidraw.com
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'

View File

@@ -5,4 +5,4 @@ package-lock.json
firebase/
dist/
public/workbox
src/packages/excalidraw/types
packages/excalidraw/types

View File

@@ -23,5 +23,5 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Auto release
run: |
yarn add @actions/core
yarn add @actions/core -W
yarn autorelease

View File

@@ -44,7 +44,7 @@ jobs:
- name: Auto release preview
id: "autorelease"
run: |
yarn add @actions/core
yarn add @actions/core -W
yarn autorelease preview ${{ github.event.issue.number }}
- name: Post comment post release
if: always()

View File

@@ -16,7 +16,7 @@ jobs:
- name: Install and lint
run: |
yarn --frozen-lockfile
yarn install
yarn test:other
yarn test:code
yarn test:typecheck

View File

@@ -22,11 +22,11 @@ jobs:
- name: Create report file
run: |
yarn locales-coverage
FILE_CHANGED=$(git diff src/locales/percentages.json)
FILE_CHANGED=$(git diff packages/excalidraw/locales/percentages.json)
if [ ! -z "${FILE_CHANGED}" ]; then
git config --global user.name 'Excalidraw Bot'
git config --global user.email 'bot@excalidraw.com'
git add src/locales/percentages.json
git add packages/excalidraw/locales/percentages.json
git commit -am "Auto commit: Calculate translation coverage"
git push
fi

View File

@@ -15,16 +15,14 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 18.x
- name: Install
run: yarn --frozen-lockfile
- name: Install in src/packages/excalidraw
run: yarn --frozen-lockfile
working-directory: src/packages/excalidraw
- name: Install in packages/excalidraw
run: yarn
working-directory: packages/excalidraw
env:
CI: true
- uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build:umd
build_script: build:esm
skip_step: install
directory: src/packages/excalidraw
directory: packages/excalidraw

View File

@@ -16,7 +16,7 @@ jobs:
with:
node-version: "18.x"
- name: "Install Deps"
run: yarn --frozen-lockfile
run: yarn install
- name: "Test Coverage"
run: yarn test:coverage
- name: "Report Coverage"

View File

@@ -13,5 +13,5 @@ jobs:
node-version: 18.x
- name: Install and test
run: |
yarn --frozen-lockfile
yarn install
yarn test:app

7
.gitignore vendored
View File

@@ -21,10 +21,9 @@ npm-debug.log*
package-lock.json
yarn-debug.log*
yarn-error.log*
src/packages/excalidraw/types
src/packages/excalidraw/example/public/bundle.js
src/packages/excalidraw/example/public/excalidraw-assets-dev
src/packages/excalidraw/example/public/excalidraw.development.js
packages/excalidraw/types
coverage
dev-dist
html
examples/**/bundle.*
meta*.json

View File

@@ -85,7 +85,7 @@ We'll be adding these features as drop-in plugins for the npm package in the fut
## Quick start
Install the [Excalidraw npm package](https://www.npmjs.com/package/@excalidraw/excalidraw):
**Note:** following instructions are for installing the Excalidraw [npm package](https://www.npmjs.com/package/@excalidraw/excalidraw) when integrating Excalidraw into your own app. To run the repository locally for development, please refer to our [Development Guide](https://docs.excalidraw.com/docs/introduction/development).
```
npm install react react-dom @excalidraw/excalidraw
@@ -97,7 +97,7 @@ or via yarn
yarn add react react-dom @excalidraw/excalidraw
```
Don't forget to check out our [Documentation](https://docs.excalidraw.com)!
Check out our [documentation](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/installation) for more details!
## Contributing

View File

@@ -1,3 +1,3 @@
files:
- source: /src/locales/en.json
translation: /src/locales/%locale%.json
- source: /packages/excalidraw/locales/en.json
translation: /packages/excalidraw/locales/%locale%.json

View File

@@ -133,7 +133,7 @@ function App() {
}
```
Here is a [complete list](https://github.com/excalidraw/excalidraw/blob/master/src/components/mainMenu/DefaultItems.tsx) of the default items.
Here is a [complete list](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/components/mainMenu/DefaultItems.tsx) of the default items.
### MainMenu.Group

View File

@@ -37,7 +37,7 @@ Defaults to `THEME.LIGHT` unless passed in `initialData.appState.theme`
### MIME_TYPES
[`MIME_TYPES`](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L101) contains all the mime types supported by `Excalidraw`.
[`MIME_TYPES`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L101) contains all the mime types supported by `Excalidraw`.
**How to use **

View File

@@ -2,9 +2,9 @@
We support a simplified API to make it easier to generate Excalidraw elements programmatically. This API is in beta and subject to change before stable. You can check the [PR](https://github.com/excalidraw/excalidraw/pull/6546) for more details.
For this purpose we introduced a new type [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133). This is the simplified version of [`ExcalidrawElement`](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L134) type with the minimum possible attributes so that creating elements programmatically is much easier (especially for cases like binding arrows or creating text containers).
For this purpose we introduced a new type [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133). This is the simplified version of [`ExcalidrawElement`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L134) type with the minimum possible attributes so that creating elements programmatically is much easier (especially for cases like binding arrows or creating text containers).
The [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133) can be converted to fully qualified Excalidraw elements by using [`convertToExcalidrawElements`](/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton#converttoexcalidrawelements).
The [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133) can be converted to fully qualified Excalidraw elements by using [`convertToExcalidrawElements`](/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton#converttoexcalidrawelements).
## convertToExcalidrawElements
@@ -19,7 +19,7 @@ convertToExcalidrawElements(
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `elements` | [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L137) | | The Excalidraw element Skeleton which needs to be converted to Excalidraw elements. |
| `elements` | [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L137) | | The Excalidraw element Skeleton which needs to be converted to Excalidraw elements. |
| `opts` | `{ regenerateIds: boolean }` | ` {regenerateIds: true}` | By default `id` will be regenerated for all the elements irrespective of whether you pass the `id` so if you don't want the ids to regenerated, you can set this attribute to `false`. |
**_How to use_**
@@ -71,7 +71,7 @@ function App() {
}
```
You can pass additional [`properties`](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L27) as well to decorate the shapes.
You can pass additional [`properties`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L27) as well to decorate the shapes.
:::info
@@ -192,7 +192,7 @@ convertToExcalidrawElements([
### Text Containers
In addition to `type`, `x` and `y` properties, [`label`](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L124C7-L130C59) property is required for text containers. The `text` property in `label` is required, rest of the attributes are optional.
In addition to `type`, `x` and `y` properties, [`label`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L124C7-L130C59) property is required for text containers. The `text` property in `label` is required, rest of the attributes are optional.
If you don't provide the dimensions of container, we calculate it based of the label dimensions.
@@ -326,7 +326,7 @@ convertToExcalidrawElements([
### Arrow bindings
To bind arrow to a shape you need to specify its [`start`](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L86) and [`end`](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L54) properties. You need to pass either `type` or `id` property in `start` and `end` properties, rest of the attributes are optional
To bind arrow to a shape you need to specify its [`start`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L86) and [`end`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L54) properties. You need to pass either `type` or `id` property in `start` and `end` properties, rest of the attributes are optional
```js
convertToExcalidrawElements([

View File

@@ -2,7 +2,7 @@
<pre>
(api:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L616">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L616">
ExcalidrawAPI
</a>
) => void;
@@ -17,7 +17,7 @@ export default function App() {
}
```
You can use this prop when you want to access some [Excalidraw APIs](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L616). We expose the below APIs :point_down:
You can use this prop when you want to access some [Excalidraw APIs](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L616). We expose the below APIs :point_down:
| API | Signature | Usage |
| --- | --- | --- |
@@ -37,7 +37,7 @@ You can use this prop when you want to access some [Excalidraw APIs](https://git
| [setActiveTool](#setactivetool) | `function` | This API can be used to set the active tool |
| [setCursor](#setcursor) | `function` | This API can be used to set customise the mouse cursor on the canvas |
| [resetCursor](#resetcursor) | `function` | This API can be used to reset to default mouse cursor on the canvas |
| [toggleMenu](#togglemenu) | `function` | Toggles specific menus on/off |
| [toggleSidebar](#toggleSidebar) | `function` | Toggles specific sidebar on/off |
| [onChange](#onChange) | `function` | Subscribes to change events |
| [onPointerDown](#onPointerDown) | `function` | Subscribes to `pointerdown` events |
| [onPointerUp](#onPointerUp) | `function` | Subscribes to `pointerup` events |
@@ -52,7 +52,7 @@ Additionally `ready` and `readyPromise` from the API have been discontinued. The
<pre>
(scene:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L339">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L339">
sceneData
</a>
) => void
@@ -62,9 +62,9 @@ You can use this function to update the scene with the sceneData. It accepts the
| Name | Type | Description |
| --- | --- | --- |
| `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L38) | The `elements` to be updated in the scene |
| `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L39) | The `appState` to be updated in the scene. |
| `collaborators` | <code>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">Collaborator></a></code> | The list of collaborators to be updated in the scene. |
| `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L38) | The `elements` to be updated in the scene |
| `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L39) | The `appState` to be updated in the scene. |
| `collaborators` | <code>Map<string, <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L37">Collaborator></a></code> | The list of collaborators to be updated in the scene. |
| `commitToHistory` | `boolean` | Implies if the `history (undo/redo)` should be recorded. Defaults to `false`. |
```jsx live
@@ -125,13 +125,13 @@ function App() {
<pre>
(opts: &#123; <br /> libraryItems:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L249">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L249">
LibraryItemsSource
</a>
;<br /> merge?: boolean; <br /> prompt?: boolean;
<br /> openLibraryMenu?: boolean;
<br /> defaultStatus?: "unpublished" | "published"; <br /> &#125;) => Promise&lt;
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L246">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L246">
LibraryItems
</a>
&gt;
@@ -141,7 +141,7 @@ You can use this function to update the library. It accepts the below attributes
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `libraryItems` | [LibraryItemsSource](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L249) | \_ | The `libraryItems` to be replaced/merged with current library |
| `libraryItems` | [LibraryItemsSource](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L249) | \_ | The `libraryItems` to be replaced/merged with current library |
| `merge` | boolean | `false` | Whether to merge with existing library items. |
| `prompt` | boolean | `false` | Whether to prompt user for confirmation. |
| `openLibraryMenu` | boolean | `false` | Keep the library menu open after library is updated. |
@@ -189,7 +189,7 @@ function App() {
</button>
<Excalidraw
ref={(api) => setExcalidrawAPI(api)}
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/src/initialData.js
// initial data retrieved from https://github.com/excalidraw/excalidraw/blob/master/dev-docs/packages/excalidraw/initialData.js
initialData={{
libraryItems: initialData.libraryItems,
appState: { openSidebar: "library" },
@@ -204,7 +204,7 @@ function App() {
<pre>
(files:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59">
BinaryFileData
</a>
) => void
@@ -224,7 +224,7 @@ Resets the scene. If `resetLoadingState` is passed as true then it will also for
<pre>
() =>{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
ExcalidrawElement[]
</a>
</pre>
@@ -235,7 +235,7 @@ Returns all the elements including the deleted in the scene.
<pre>
() => NonDeleted&#60;
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115">
ExcalidrawElement
</a>
[]&#62;
@@ -247,7 +247,7 @@ Returns all the elements excluding the deleted in the scene
<pre>
() =>{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
AppState
</a>
</pre>
@@ -288,7 +288,7 @@ Scroll the nearest element out of the elements supplied to the center of the vie
| Attribute | type | default | Description |
| --- | --- | --- | --- |
| target | [ExcalidrawElement](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115) &#124; [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L115) | All scene elements | The element(s) to scroll to. |
| target | [ExcalidrawElement](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115) &#124; [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L115) | All scene elements | The element(s) to scroll to. |
| opts.fitToContent | boolean | false | Whether to fit the elements to viewport by automatically changing zoom as needed. Note that the zoom range is between 10%-100%. |
| opts.fitToViewport | boolean | false | Similar to fitToContent but the zoom range is not limited. If elements are smaller than the viewport, zoom will go above 100%. |
| opts.viewportZoomFactor | number | 0.7 | when fitToViewport=true, how much screen should the content cover, between 0.1 (10%) and 1 (100%) |
@@ -336,7 +336,7 @@ The unique id of the excalidraw component. This can be used to identify the exca
<pre>
() =>{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L82">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L82">
files
</a>
</pre>
@@ -364,7 +364,7 @@ This API has the below signature. It sets the `tool` passed in param as the acti
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | [ToolType](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L91) | `selection` | The tool type which should be set as active tool. When setting `image` as active tool, the insertion onto canvas when using image tool is disabled by default, so you can enable it by setting `insertOnCanvasDirectly` to `true` |
| `type` | [ToolType](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L91) | `selection` | The tool type which should be set as active tool. When setting `image` as active tool, the insertion onto canvas when using image tool is disabled by default, so you can enable it by setting `insertOnCanvasDirectly` to `true` |
| `locked` | `boolean` | `false` | Indicates whether the the active tool should be locked. It behaves the same way when using the `lock` tool in the editor interface |
## setCursor

View File

@@ -1,18 +1,18 @@
# initialData
<pre>
&#123; elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> &#125;
&#123; elements?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>, appState?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> &#125;
</pre>
This helps to load Excalidraw with `initialData`. It must be an object or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to an object containing the below optional fields.
| Name | Type | Description |
| --- | --- | --- |
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | The `elements` with which `Excalidraw` should be mounted. |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) | The `AppState` with which `Excalidraw` should be mounted. |
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | The `elements` with which `Excalidraw` should be mounted. |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) | The `AppState` with which `Excalidraw` should be mounted. |
| `scrollToContent` | `boolean` | This attribute indicates whether to `scroll` to the nearest element to center once `Excalidraw` is mounted. By default, it will not scroll the nearest element to the center. Make sure you pass `initialData.appState.scrollX` and `initialData.appState.scrollY` when `scrollToContent` is false so that scroll positions are retained |
| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L247) &#124; Promise&lt;[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200)&gt; | This library items with which `Excalidraw` should be mounted. |
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L82) | The `files` added to the scene. |
| `libraryItems` | [LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L247) &#124; Promise&lt;[LibraryItems](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200)&gt; | This library items with which `Excalidraw` should be mounted. |
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L82) | The `files` added to the scene. |
You might want to use this when you want to load excalidraw with some initial elements and app state.

View File

@@ -23,7 +23,7 @@ All `props` are _optional_.
| [`libraryReturnUrl`](#libraryreturnurl) | `string` | _ | What URL should [libraries.excalidraw.com](https://libraries.excalidraw.com) be installed to |
| [`theme`](#theme) | `"light"` &#124; `"dark"` | `"light"` | The theme of the Excalidraw component |
| [`name`](#name) | `string` | | Name of the drawing |
| [`UIOptions`](/docs/@excalidraw/excalidraw/api/props/ui-options) | `object` | [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L151) | To customise UI options. Currently we support customising [`canvas actions`](#canvasactions) |
| [`UIOptions`](/docs/@excalidraw/excalidraw/api/props/ui-options) | `object` | [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L151) | To customise UI options. Currently we support customising [`canvas actions`](/docs/@excalidraw/excalidraw/api/props/ui-options#canvasactions) |
| [`detectScroll`](#detectscroll) | `boolean` | `true` | Indicates whether to update the offsets when nearest ancestor is scrolled. |
| [`handleKeyboardGlobally`](#handlekeyboardglobally) | `boolean` | `false` | Indicates whether to bind the keyboard events to document. |
| [`autoFocus`](#autofocus) | `boolean` | `false` | indicates whether to focus the Excalidraw component on page load |
@@ -33,7 +33,7 @@ All `props` are _optional_.
### Storing custom data on Excalidraw elements
Beyond attributes that Excalidraw elements already support, you can store `custom` data on each `element` in a `customData` object. The type of the attribute is [`Record<string, any>`](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L66) and is optional.
Beyond attributes that Excalidraw elements already support, you can store `custom` data on each `element` in a `customData` object. The type of the attribute is [`Record<string, any>`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L66) and is optional.
You can use this to add any extra information you need to keep track of.
@@ -59,11 +59,11 @@ Every time component updates, this callback if passed will get triggered and has
(excalidrawElements, appState, files) => void;
```
1. `excalidrawElements`: Array of [excalidrawElements](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) in the scene.
1. `excalidrawElements`: Array of [excalidrawElements](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) in the scene.
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) of the scene.
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) of the scene.
3. `files`: The [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L64) which are added to the scene.
3. `files`: The [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L64) which are added to the scene.
Here you can try saving the data to your backend or local storage for example.
@@ -79,14 +79,14 @@ This callback is triggered when mouse pointer is updated.
2.`button`: The position of the button. This will be one of `["down", "up"]`
3.`pointersMap`: [`pointers`](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L131) map of the scene
3.`pointersMap`: [`pointers`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L131) map of the scene
```js
(exportedElements, appState, canvas) => void
```
1. `exportedElements`: An array of [non deleted elements](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L87) which needs to be exported.
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) of the scene.
1. `exportedElements`: An array of [non deleted elements](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L87) which needs to be exported.
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) of the scene.
3. `canvas`: The `HTMLCanvasElement` of the scene.
### onPointerDown
@@ -96,11 +96,11 @@ This prop if passed will be triggered on pointer down events and has the below s
<pre>
(activeTool:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L115">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L115">
{" "}
AppState["activeTool"]
</a>
, pointerDownState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L424">
, pointerDownState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L424">
PointerDownState
</a>) => void
</pre>
@@ -119,7 +119,7 @@ This callback is triggered if passed when something is pasted into the scene. Yo
<pre>
(data:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/clipboard.ts#L18">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/clipboard.ts#L18">
ClipboardData
</a>
, event: ClipboardEvent &#124; null) => boolean
@@ -135,7 +135,7 @@ This callback if supplied will get triggered when the library is updated and has
<pre>
(items:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">
LibraryItems
</a>
) => void | Promise&lt;any&gt;
@@ -149,7 +149,7 @@ This prop if passed will be triggered when clicked on `link`. To handle the redi
<pre>
(element:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">
ExcalidrawElement
</a>
, event: CustomEvent&lt;&#123; nativeEvent: MouseEvent }&gt;) => void
@@ -182,7 +182,7 @@ const onLinkOpen: ExcalidrawProps["onLinkOpen"] = useCallback(
### langCode
Determines the `language` of the UI. It should be one of the [available language codes](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L14). Defaults to `en` (English). We also export default language and supported languages which you can import as shown below.
Determines the `language` of the UI. It should be one of the [available language codes](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L14). Defaults to `en` (English). We also export default language and supported languages which you can import as shown below.
```js
import { defaultLang, languages } from "@excalidraw/excalidraw";
@@ -191,7 +191,7 @@ import { defaultLang, languages } from "@excalidraw/excalidraw";
| name | type |
| --- | --- |
| `defaultLang` | `string` |
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L15) |
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
### viewModeEnabled

View File

@@ -4,7 +4,7 @@
<pre>
(isMobile: boolean, appState:
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
AppState
</a>) => JSX | null
</pre>
@@ -66,7 +66,7 @@ function App() {
<pre>
(element: NonDeleted&lt;ExcalidrawEmbeddableElement&gt;, appState:{" "}
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">
AppState
</a>
) => JSX.Element | null

View File

@@ -4,7 +4,7 @@ This prop can be used to customise UI of Excalidraw. Currently we support custom
<pre>
&#123;
<br /> canvasActions?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L372">
<br /> canvasActions?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L372">
CanvasActions
</a>, <br /> dockedSidebarBreakpoint?: number, <br /> welcomeScreen?: boolean <br />
@@ -55,7 +55,7 @@ If `UIOptions.canvasActions.export` is `false` the export button will not be ren
## dockedSidebarBreakpoint
This prop indicates at what point should we break to a docked, permanent sidebar. If not passed it defaults to [`MQ_RIGHT_SIDEBAR_MAX_WIDTH_PORTRAIT`](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L161).
This prop indicates at what point should we break to a docked, permanent sidebar. If not passed it defaults to [`MQ_RIGHT_SIDEBAR_MAX_WIDTH_PORTRAIT`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/constants.ts#L161).
If the _width_ of the _excalidraw_ container exceeds _dockedSidebarBreakpoint_, the sidebar will be `dockable` and the button to `dock` the sidebar will be shown
If user choses to `dock` the sidebar, it will push the right part of the UI towards the left, making space for the sidebar as shown below.
@@ -73,9 +73,9 @@ function App() {
## tools
This `prop ` controls the visibility of the tools in the editor.
This `prop` controls the visibility of the tools in the editor.
Currently you can control the visibility of `image` tool via this prop.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| image | boolean | true | Decides whether `image` tool should be visible.
| image | boolean | true | Decides whether `image` tool should be visible.

View File

@@ -20,16 +20,16 @@ exportToCanvas(&#123;<br/>&nbsp;
getDimensions,<br/>&nbsp;
files,<br/>&nbsp;
exportPadding?: number;<br/>
&#125;: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a>
&#125;: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L21">ExportOpts</a>
</pre>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `elements` | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | | The elements to be exported to canvas. |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L23) | [Default App State](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L17) | The app state of the scene. |
| `elements` | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | | The elements to be exported to canvas. |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L23) | [Default App State](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/appState.ts#L17) | The app state of the scene. |
| [`getDimensions`](#getdimensions) | `function` | _ | A function which returns the `width`, `height`, and optionally `scale` (defaults to `1`), with which canvas is to be exported. |
| `maxWidthOrHeight` | `number` | _ | The maximum `width` or `height` of the exported image. If provided, `getDimensions` is ignored. |
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59) | _ | The files added to the scene. |
| `files` | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59) | _ | The files added to the scene. |
| `exportPadding` | `number` | `10` | The `padding` to be added on canvas. |
@@ -105,7 +105,7 @@ function App() {
<pre>
exportToBlob(<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L14">ExportOpts</a> & &#123;<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L14">ExportOpts</a> & &#123;<br/>&nbsp;
mimeType?: string,<br/>&nbsp;
quality?: number,<br/>&nbsp;
exportPadding?: number;<br/>
@@ -134,16 +134,16 @@ Returns a promise which resolves with a [blob](https://developer.mozilla.org/en-
<pre>
exportToSvg(&#123;<br/>&nbsp;
elements:&nbsp;
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">
ExcalidrawElement[]
</a>,<br/>&nbsp;
appState:
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95"> AppState
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95"> AppState
</a>,<br/>&nbsp;
exportPadding: number,<br/>&nbsp;
metadata: string,<br/>&nbsp;
files:&nbsp;
<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L59">
<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L59">
BinaryFiles
</a>,<br/>
&#125;);
@@ -151,10 +151,10 @@ exportToSvg(&#123;<br/>&nbsp;
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114) | | The elements to exported as `svg `|
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L11) | The `appState` of the scene |
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114) | | The elements to exported as `svg `|
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/appState.ts#L11) | The `appState` of the scene |
| exportPadding | number | 10 | The `padding` to be added on canvas |
| files | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L64) | undefined | The `files` added to the scene. |
| files | [BinaryFiles](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L64) | undefined | The `files` added to the scene. |
This function returns a promise which resolves to `svg` of the exported drawing.
@@ -164,7 +164,7 @@ This function returns a promise which resolves to `svg` of the exported drawing.
<pre>
exportToClipboard(<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L21">ExportOpts</a> & &#123;<br/>&nbsp;
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/utils.ts#L21">ExportOpts</a> & &#123;<br/>&nbsp;
mimeType?: string,<br/>&nbsp;
quality?: number;<br/>&nbsp;
type: 'png' | 'svg' |'json'<br/>

View File

@@ -8,7 +8,7 @@ id: "restore"
**_Signature_**
<pre>
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["appState"]</a>,<br/>&nbsp; localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState["appState"]</a>,<br/>&nbsp; localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>
</pre>
**_How to use_**
@@ -17,7 +17,7 @@ restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob
import { restoreAppState } from "@excalidraw/excalidraw";
```
This function will make sure all the `keys` have appropriate `values` in [appState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95) and if any key is missing, it will be set to its `default` value.
This function will make sure all the `keys` have appropriate `values` in [appState](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95) and if any key is missing, it will be set to its `default` value.
When `localAppState` is supplied, it's used in place of values that are missing (`undefined`) in `appState` instead of the defaults.
Use this as a way to not override user's defaults if you persist them.
@@ -29,16 +29,16 @@ You can pass `null` / `undefined` if not applicable.
<pre>
restoreElements(
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ImportedDataState["elements"]</a>,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
opts: &#123; refreshDimensions?: boolean, repairBindings?: boolean }<br/>
)
</pre>
| Prop | Type | Description |
| ---- | ---- | ---- |
| `elements` | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ImportedDataState["elements"]</a> | The `elements` to be restored |
| [`localElements`](#localelements) | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> &#124; null &#124; undefined | When `localElements` are supplied, they are used to ensure that existing restored elements reuse `version` (and increment it), and regenerate `versionNonce`. |
| `elements` | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ImportedDataState["elements"]</a> | The `elements` to be restored |
| [`localElements`](#localelements) | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> &#124; null &#124; undefined | When `localElements` are supplied, they are used to ensure that existing restored elements reuse `version` (and increment it), and regenerate `versionNonce`. |
| [`opts`](#opts) | `Object` | The extra optional parameter to configure restored elements
#### localElements
@@ -70,15 +70,15 @@ Parameter `refreshDimensions` indicates whether we should also `recalculate` tex
<pre>
restore(
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState</a>,<br/>&nbsp;
localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>> | null | undefined,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined<br/>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L4">DataState</a><br/>
data: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState</a>,<br/>&nbsp;
localAppState: Partial&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>> | null | undefined,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null | undefined<br/>): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L4">DataState</a><br/>
opts: &#123; refreshDimensions?: boolean, repairBindings?: boolean }<br/>
)
</pre>
See [`restoreAppState()`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreAppState) about `localAppState`, and [`restoreElements()`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreElements) about `localElements`.
See [`restoreAppState()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/excalidraw/README.md#restoreAppState) about `localAppState`, and [`restoreElements()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/packages/excalidraw/README.md#restoreElements) about `localElements`.
**_How to use_**
@@ -93,7 +93,7 @@ This function makes sure elements and state is set to appropriate values and set
**_Signature_**
<pre>
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>&nbsp;
restoreLibraryItems(libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L34">ImportedDataState["libraryItems"]</a>,<br/>&nbsp;
defaultStatus: "published" | "unpublished")
</pre>

View File

@@ -8,7 +8,7 @@ These are pure Javascript functions exported from the @excalidraw/excalidraw [`@
### serializeAsJSON
Takes the scene elements and state and returns a JSON string. `Deleted` elements as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L42) source for details).
Takes the scene elements and state and returns a JSON string. `Deleted` elements as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/json.ts#L42) source for details).
If you want to overwrite the `source` field in the `JSON` string, you can set `window.EXCALIDRAW_EXPORT_SOURCE` to the desired value.
@@ -16,8 +16,8 @@ If you want to overwrite the `source` field in the `JSON` string, you can set `w
<pre>
serializeAsJSON(&#123;<br/>&nbsp;
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a>,<br/>
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>,<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a>,<br/>
}): string
</pre>
@@ -37,7 +37,7 @@ If you want to overwrite the source field in the JSON string, you can set `windo
<pre>
serializeLibraryAsJSON(
libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">LibraryItems[]</a>)
libraryItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">LibraryItems[]</a>)
</pre>
**How to use**
@@ -53,7 +53,7 @@ Returns `true` if element is invisibly small (e.g. width & height are zero).
**_Signature_**
<pre>
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement</a>): boolean
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement</a>): boolean
</pre>
**How to use**
@@ -80,10 +80,10 @@ excalidrawAPI.updateScene(scene);
<pre>
loadFromBlob(<br/>&nbsp;
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
fileHandle?: FileSystemHandle | null <br/>
) => Promise&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L61">RestoredDataState</a>>
) => Promise&lt;<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/restore.ts#L61">RestoredDataState</a>>
</pre>
### loadLibraryFromBlob
@@ -130,10 +130,10 @@ if (contents.type === MIME_TYPES.excalidraw) {
<pre>
loadSceneOrLibraryFromBlob(<br/>&nbsp;
blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a> | null,<br/>&nbsp;
localElements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a> | null,<br/>&nbsp;
fileHandle?: FileSystemHandle | null<br/>
) => Promise&lt;&#123; type: string, data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L53">RestoredDataState</a> | <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L33">ImportedLibraryState</a>}>
) => Promise&lt;&#123; type: string, data: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/restore.ts#L53">RestoredDataState</a> | <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L33">ImportedLibraryState</a>}>
</pre>
### getFreeDrawSvgPath
@@ -149,7 +149,7 @@ import { getFreeDrawSvgPath } from "@excalidraw/excalidraw";
**Signature**
<pre>
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L182">ExcalidrawFreeDrawElement</a>)
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L182">ExcalidrawFreeDrawElement</a>)
</pre>
### isLinearElement
@@ -165,7 +165,7 @@ import { isLinearElement } from "@excalidraw/excalidraw";
**Signature**
<pre>
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L80">ExcalidrawElement</a>): boolean
isLinearElement(elementType?: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L80">ExcalidrawElement</a>): boolean
</pre>
### getNonDeletedElements
@@ -181,7 +181,7 @@ import { getNonDeletedElements } from "@excalidraw/excalidraw";
**Signature**
<pre>
getNonDeletedElements(elements:<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114"> readonly ExcalidrawElement[]</a>): as readonly <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L125">NonDeletedExcalidrawElement[]</a>
getNonDeletedElements(elements:<a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114"> readonly ExcalidrawElement[]</a>): as readonly <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L125">NonDeletedExcalidrawElement[]</a>
</pre>
### mergeLibraryItems
@@ -196,9 +196,9 @@ import { mergeLibraryItems } from "@excalidraw/excalidraw";
<pre>
mergeLibraryItems(<br/>&nbsp;
localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L250">LibraryItems</a>,<br/>&nbsp;
otherItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L200">LibraryItems</a><br/>
): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L250">LibraryItems</a>
localItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L250">LibraryItems</a>,<br/>&nbsp;
otherItems: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L200">LibraryItems</a><br/>
): <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L250">LibraryItems</a>
</pre>
### parseLibraryTokensFromUrl
@@ -239,8 +239,8 @@ export const App = () => {
<pre>
useHandleLibrary(opts: &#123;<br/>&nbsp;
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L494">ExcalidrawAPI</a>,<br/>&nbsp;
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L253">LibraryItemsSource</a><br/>
excalidrawAPI: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L494">ExcalidrawAPI</a>,<br/>&nbsp;
getInitialLibraryItems?: () => <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L253">LibraryItemsSource</a><br/>
});
</pre>
@@ -253,7 +253,7 @@ This function returns the current `scene` version.
**_Signature_**
<pre>
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L114">ExcalidrawElement[]</a>)
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L114">ExcalidrawElement[]</a>)
</pre>
**How to use**
@@ -274,7 +274,7 @@ import { sceneCoordsToViewportCoords } from "@excalidraw/excalidraw";
<pre>
sceneCoordsToViewportCoords(&#123; sceneX: number, sceneY: number },<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): &#123; x: number, y: number }
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): &#123; x: number, y: number }
</pre>
### viewportCoordsToSceneCoords
@@ -289,7 +289,7 @@ import { viewportCoordsToSceneCoords } from "@excalidraw/excalidraw";
<pre>
viewportCoordsToSceneCoords(&#123; clientX: number, clientY: number },<br/>&nbsp;
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L95">AppState</a><br/>): &#123;x: number, y: number}
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/types.ts#L95">AppState</a><br/>): &#123;x: number, y: number}
</pre>
### useDevice
@@ -350,8 +350,8 @@ To help with localization, we export the following.
| name | type |
| --- | --- |
| `defaultLang` | `string` |
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L15) |
| `useI18n` | [`() => { langCode, t }`](https://github.com/excalidraw/excalidraw/blob/master/src/i18n.ts#L15) |
| `languages` | [`Language[]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
| `useI18n` | [`() => { langCode, t }`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/i18n.ts#L15) |
```js
import { defaultLang, languages, useI18n } from "@excalidraw/excalidraw";

View File

@@ -21,7 +21,7 @@ Most notably, you can customize the primary colors, by overriding these variable
- `--color-primary-light`
- `--color-primary-contrast-offset` — a slightly darker (in light mode), or lighter (in dark mode) `--color-primary` color to fix contrast issues (see [Chubb illusion](https://en.wikipedia.org/wiki/Chubb_illusion)). It will fall back to `--color-primary` if not present.
For a complete list of variables, check [theme.scss](https://github.com/excalidraw/excalidraw/blob/master/src/css/theme.scss), though most of them will not make sense to override.
For a complete list of variables, check [theme.scss](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/css/theme.scss), though most of them will not make sense to override.
```css showLineNumbers
.custom-styles .excalidraw {

View File

@@ -13,7 +13,7 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the
1. Install the dependencies
```bash
cd src/packages/excalidraw && yarn
cd packages/excalidraw && yarn
```
2. Start the example app

View File

@@ -39,7 +39,7 @@ Since Vite removes env variables by default, you can update the vite config to e
```
define: {
"process.env.IS_PREACT": process.env.IS_PREACT,
"process.env.IS_PREACT": JSON.stringify("true"),
},
```

View File

@@ -32,15 +32,9 @@ function App() {
### Next.js
Since _Excalidraw_ doesn't support server side rendering, you should render the component once the host is `mounted`.
Since Excalidraw doesn't support `server side rendering` so it should be rendered only on `client`. The way to achieve this in next.js is using `next.js dynamic import`.
Here are two ways on how you can render **Excalidraw** on **Next.js**.
1. Using **Next.js Dynamic** import [Recommended].
Since Excalidraw doesn't support server side rendering so you can also use `dynamic import` to render by setting `ssr` to `false`.
If you want to only import `Excalidraw` component you can do :point_down:
```jsx showLineNumbers
import dynamic from "next/dynamic";
@@ -55,25 +49,88 @@ export default function App() {
}
```
Here is a working [demo](https://codesandbox.io/p/sandbox/excalidraw-with-next-dynamic-k8yjq2).
However the above component only works for named component exports. If you want to import some util / constant or something else apart from Excalidraw, then this approach will not work. Instead you can write a wrapper over Excalidraw and import the wrapper dynamically.
If you are using `pages router` then importing the wrapper dynamically would work, where as if you are using `app router` then you will have to also add `useClient` directive on top of the file in addition to dynamically importing the wrapper as shown :point_down:
2. Importing Excalidraw once **client** is rendered.
<Tabs>
<TabItem value="Excalidraw Wrapper" label="Excalidraw Wrapper" >
```jsx showLineNumbers
import { useState, useEffect } from "react";
export default function App() {
const [Excalidraw, setExcalidraw] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) =>
setExcalidraw(comp.Excalidraw),
```jsx showLineNumbers
"use client";
import { Excalidraw, convertToExcalidrawElements } from "@excalidraw/excalidraw";
import "@excalidraw/excalidraw/index.css";
const ExcalidrawWrapper: React.FC = () => {
console.info(convertToExcalidrawElements([{
type: "rectangle",
id: "rect-1",
width: 186.47265625,
height: 141.9765625,
},]));
return (
<div style={{height:"500px", width:"500px"}}>
<Excalidraw />
</div>
);
}, []);
return <>{Excalidraw && <Excalidraw />}</>;
}
```
};
export default ExcalidrawWrapper;
```
</TabItem>
<TabItem value="pages" label="Pages router">
```jsx showLineNumbers
import dynamic from "next/dynamic";
// Since client components get prerenderd on server as well hence importing
// the excalidraw stuff dynamically with ssr false
const ExcalidrawWrapper = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<ExcalidrawWrapper />
);
}
```
</TabItem>
<TabItem value="app" label="App router">
```jsx showLineNumbers
import dynamic from "next/dynamic";
// Since client components get prerenderd on server as well hence importing
// the excalidraw stuff dynamically with ssr false
const ExcalidrawWrapper = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<ExcalidrawWrapper />
);
}
```
</TabItem>
</Tabs>
Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/excalidraw/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs-gh6smrdnq-excalidraw.vercel.app/).
Here is a working [demo](https://codesandbox.io/p/sandbox/excalidraw-with-next-5xb3d)
The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm)
@@ -93,7 +150,7 @@ Since Vite removes env variables by default, you can update the vite config to e
```
define: {
"process.env.IS_PREACT": process.env.IS_PREACT,
"process.env.IS_PREACT": JSON.stringify("true"),
},
```
:::
@@ -148,7 +205,7 @@ import TabItem from "@theme/TabItem";
<h1>Excalidraw Embed Example</h1>
<div id="app"></div>
</div>
<script type="text/javascript" src="src/index.js"></script>
<script type="text/javascript" src="packages/excalidraw/index.js"></script>
</body>
</html>
```

View File

@@ -38,9 +38,9 @@ Add the diagram type in switch case in [`parseMermaid`](https://github.com/excal
## Writing the Excalidraw Skeleton Convertor
With the completion of previous step, we have all the data, now we need to transform it so to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133) format.
With the completion of previous step, we have all the data, now we need to transform it so to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133) format.
Similar to [`FlowChartToExcalidrawSkeletonConverter`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24), you have to write the `{{diagramType}}ToExcalidrawSkeletonConverter` which parses the data received in previous step and returns the [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133).
Similar to [`FlowChartToExcalidrawSkeletonConverter`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24), you have to write the `{{diagramType}}ToExcalidrawSkeletonConverter` which parses the data received in previous step and returns the [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133).
Thats it, you have added the new diagram type 🥳, now lets test it out!

View File

@@ -6,7 +6,7 @@ In this section we will be diving into how the [flowchart parser](https://github
![image](https://github.com/excalidraw/excalidraw/assets/11256141/2a097bbb-64bf-49d6-bf7f-21172bdb538d)
We use `diagram.parser.yy` attribute to parse the data. If you want to know more about how the `diagram.parse.yy` attribute looks like, you can check it [here](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/diagrams/flowchart/flowDb.js#L768), however for scope of flowchart we are using **3** APIs from this parser to compute `vertices`, `edges` and `clusters` as we need these data to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133C13-L133C38).
We use `diagram.parser.yy` attribute to parse the data. If you want to know more about how the `diagram.parse.yy` attribute looks like, you can check it [here](https://github.com/mermaid-js/mermaid/blob/00d06c7282a701849793680c1e97da1cfdfcce62/packages/mermaid/src/diagrams/flowchart/flowDb.js#L768), however for scope of flowchart we are using **3** APIs from this parser to compute `vertices`, `edges` and `clusters` as we need these data to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38).
For computing `vertices` and `edge`s lets consider the below svg generated by mermaid
@@ -42,7 +42,7 @@ Considering the same example this is the response from the API
}
}
```
The dimensions and position is missing in this response and we need that to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133C13-L133C38), for this we have our own parser [`parseVertex`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L178) which takes the above response and uses the `svg` together to compute position, dimensions and cleans up the response.
The dimensions and position is missing in this response and we need that to transform to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38), for this we have our own parser [`parseVertex`](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/parseMermaid.ts#L178) which takes the above response and uses the `svg` together to compute position, dimensions and cleans up the response.
The final output from `parseVertex` looks like :point_down:

View File

@@ -55,11 +55,11 @@ If you want to understand how flowchart parser works, you can navigate to [Flowc
## Converting to ExcalidrawElementSkeleton
Now we have all the data, we just need to transform it to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133C13-L133C38) API so it can be rendered in Excalidraw.
Now we have all the data, we just need to transform it to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38) API so it can be rendered in Excalidraw.
For this we have `converters` which takes the parsed mermaid data and gives back the Excalidraw Skeleton.
For Unsupported types, we have already mentioned above that we convert it to `dataURL` and return the ExcalidrawImageSkeleton.
For supported types, currently only flowchart, we have [flowchartConverter](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24) which parses the data and converts to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/src/data/transform.ts#L133C13-L133C38).
For supported types, currently only flowchart, we have [flowchartConverter](https://github.com/excalidraw/mermaid-to-excalidraw/blob/master/src/converter/types/flowchart.ts#L24) which parses the data and converts to [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133C13-L133C38).
![image](https://github.com/excalidraw/excalidraw/assets/11256141/00226e9d-043d-4a08-989a-3ad9d2a574f1)

View File

@@ -52,15 +52,6 @@ Make sure the title starts with a semantic prefix:
- **chore**: Other changes that don't modify src or test files
- **revert**: Reverts a previous commit
### Changelog
Add a brief description of your pull request to the changelog located here: [changelog](https://github.com/excalidraw/excalidraw/blob/master/CHANGELOG.md)
Notes:
- Make sure to prepend to the section corresponding with the semantic prefix you selected in the title
- Link to your pull request - this will require updating the CHANGELOG _after_ creating the pull request
### Testing
Once you submit your pull request it will automatically be tested. Be sure to check the results of the test and fix any issues that arise.

View File

@@ -41,10 +41,7 @@ const config = {
showLastUpdateTime: true,
},
theme: {
customCss: [
require.resolve("./src/css/custom.scss"),
require.resolve("../src/packages/excalidraw/example/App.scss"),
],
customCss: [require.resolve("./src/css/custom.scss")],
},
}),
],

4
dev-docs/vercel.json Normal file
View File

@@ -0,0 +1,4 @@
{
"outputDirectory": "build",
"installCommand": "yarn install"
}

View File

@@ -15,14 +15,23 @@
border-radius: 50%;
}
}
.app-title {
margin-block-start: 0.83em;
margin-block-end: 0.83em;
}
}
.button-wrapper button {
z-index: 1;
height: 40px;
max-width: 200px;
margin: 10px;
padding: 5px;
.button-wrapper {
input[type="checkbox"] {
margin: 5px;
}
button {
z-index: 1;
height: 40px;
max-width: 200px;
margin: 10px;
padding: 5px;
}
}
.excalidraw .App-menu_top .buttonList {

View File

@@ -1,23 +1,31 @@
import { useEffect, useState, useRef, useCallback } from "react";
import React, {
useEffect,
useState,
useRef,
useCallback,
Children,
cloneElement,
} from "react";
import ExampleSidebar from "./sidebar/ExampleSidebar";
import type * as TExcalidraw from "../index";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import "./App.scss";
import initialData from "./initialData";
import { nanoid } from "nanoid";
import {
resolvablePromise,
ResolvablePromise,
distance2d,
fileOpen,
withBatchedUpdates,
withBatchedUpdatesThrottled,
} from "../../../utils";
import { EVENT, ROUNDNESS } from "../../../constants";
import { distance2d } from "../../../math";
import { fileOpen } from "../../../data/filesystem";
import { loadSceneOrLibraryFromBlob } from "../../utils";
import {
} from "../utils";
import CustomFooter from "./CustomFooter";
import MobileFooter from "./MobileFooter";
import initialData from "../initialData";
import type {
AppState,
BinaryFileData,
ExcalidrawImperativeAPI,
@@ -25,18 +33,14 @@ import {
Gesture,
LibraryItems,
PointerDownState as ExcalidrawPointerDownState,
} from "../../../types";
import { NonDeletedExcalidrawElement, Theme } from "../../../element/types";
import { ImportedLibraryData } from "../../../data/types";
import CustomFooter from "./CustomFooter";
import MobileFooter from "./MobileFooter";
import { KEYS } from "../../../keys";
} from "@excalidraw/excalidraw/dist/excalidraw/types";
import type {
NonDeletedExcalidrawElement,
Theme,
} from "@excalidraw/excalidraw/dist/excalidraw/element/types";
import type { ImportedLibraryData } from "@excalidraw/excalidraw/dist/excalidraw/data/types";
declare global {
interface Window {
ExcalidrawLib: typeof TExcalidraw;
}
}
import "./App.scss";
type Comment = {
x: number;
@@ -57,27 +61,6 @@ type PointerDownState = {
};
};
// This is so that we use the bundled excalidraw.development.js file instead
// of the actual source code
const {
exportToCanvas,
exportToSvg,
exportToBlob,
exportToClipboard,
Excalidraw,
useHandleLibrary,
MIME_TYPES,
sceneCoordsToViewportCoords,
viewportCoordsToSceneCoords,
restoreElements,
Sidebar,
Footer,
WelcomeScreen,
MainMenu,
LiveCollaborationTrigger,
convertToExcalidrawElements,
} = window.ExcalidrawLib;
const COMMENT_ICON_DIMENSION = 32;
const COMMENT_INPUT_HEIGHT = 50;
const COMMENT_INPUT_WIDTH = 150;
@@ -86,9 +69,38 @@ export interface AppProps {
appTitle: string;
useCustom: (api: ExcalidrawImperativeAPI | null, customArgs?: any[]) => void;
customArgs?: any[];
children: React.ReactNode;
excalidrawLib: typeof TExcalidraw;
}
export default function App({ appTitle, useCustom, customArgs }: AppProps) {
export default function App({
appTitle,
useCustom,
customArgs,
children,
excalidrawLib,
}: AppProps) {
const {
exportToCanvas,
exportToSvg,
exportToBlob,
exportToClipboard,
useHandleLibrary,
MIME_TYPES,
sceneCoordsToViewportCoords,
viewportCoordsToSceneCoords,
restoreElements,
Sidebar,
Footer,
WelcomeScreen,
MainMenu,
LiveCollaborationTrigger,
convertToExcalidrawElements,
TTDDialog,
TTDDialogTrigger,
ROUNDNESS,
loadSceneOrLibraryFromBlob,
} = excalidrawLib;
const appRef = useRef<any>(null);
const [viewModeEnabled, setViewModeEnabled] = useState(false);
const [zenModeEnabled, setZenModeEnabled] = useState(false);
@@ -150,8 +162,105 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
};
};
fetchData();
}, [excalidrawAPI]);
}, [excalidrawAPI, convertToExcalidrawElements, MIME_TYPES]);
const renderExcalidraw = (children: React.ReactNode) => {
const Excalidraw: any = Children.toArray(children).find(
(child) =>
React.isValidElement(child) &&
typeof child.type !== "string" &&
//@ts-ignore
child.type.displayName === "Excalidraw",
);
if (!Excalidraw) {
return;
}
const newElement = cloneElement(
Excalidraw,
{
excalidrawAPI: (api: ExcalidrawImperativeAPI) => setExcalidrawAPI(api),
initialData: initialStatePromiseRef.current.promise,
onChange: (
elements: NonDeletedExcalidrawElement[],
state: AppState,
) => {
console.info("Elements :", elements, "State : ", state);
},
onPointerUpdate: (payload: {
pointer: { x: number; y: number };
button: "down" | "up";
pointersMap: Gesture["pointers"];
}) => setPointerData(payload),
viewModeEnabled,
zenModeEnabled,
gridModeEnabled,
theme,
name: "Custom name of drawing",
UIOptions: {
canvasActions: {
loadScene: false,
},
tools: { image: !disableImageTool },
},
renderTopRightUI,
onLinkOpen,
onPointerDown,
onScrollChange: rerenderCommentIcons,
validateEmbeddable: true,
},
<>
{excalidrawAPI && (
<Footer>
<CustomFooter
excalidrawAPI={excalidrawAPI}
excalidrawLib={excalidrawLib}
/>
</Footer>
)}
<WelcomeScreen />
<Sidebar name="custom">
<Sidebar.Tabs>
<Sidebar.Header />
<Sidebar.Tab tab="one">Tab one!</Sidebar.Tab>
<Sidebar.Tab tab="two">Tab two!</Sidebar.Tab>
<Sidebar.TabTriggers>
<Sidebar.TabTrigger tab="one">One</Sidebar.TabTrigger>
<Sidebar.TabTrigger tab="two">Two</Sidebar.TabTrigger>
</Sidebar.TabTriggers>
</Sidebar.Tabs>
</Sidebar>
<Sidebar.Trigger
name="custom"
tab="one"
style={{
position: "absolute",
left: "50%",
transform: "translateX(-50%)",
bottom: "20px",
zIndex: 9999999999999999,
}}
>
Toggle Custom Sidebar
</Sidebar.Trigger>
{renderMenu()}
{excalidrawAPI && (
<TTDDialogTrigger icon={<span>😀</span>}>
Text to diagram
</TTDDialogTrigger>
)}
<TTDDialog
onTextSubmit={async (_) => {
console.info("submit");
// sleep for 2s
await new Promise((resolve) => setTimeout(resolve, 2000));
throw new Error("error, go away now");
// return "dummy";
}}
/>
</>,
);
return newElement;
};
const renderTopRightUI = (isMobile: boolean) => {
return (
<>
@@ -335,8 +444,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
pointerDownState: PointerDownState,
) => {
return withBatchedUpdates((event) => {
window.removeEventListener(EVENT.POINTER_MOVE, pointerDownState.onMove);
window.removeEventListener(EVENT.POINTER_UP, pointerDownState.onUp);
window.removeEventListener("pointermove", pointerDownState.onMove);
window.removeEventListener("pointerup", pointerDownState.onUp);
excalidrawAPI?.setActiveTool({ type: "selection" });
const distance = distance2d(
pointerDownState.x,
@@ -400,8 +509,8 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
onPointerMoveFromPointerDownHandler(pointerDownState);
const onPointerUp =
onPointerUpFromPointerDownHandler(pointerDownState);
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
window.addEventListener("pointermove", onPointerMove);
window.addEventListener("pointerup", onPointerUp);
pointerDownState.onMove = onPointerMove;
pointerDownState.onUp = onPointerUp;
@@ -493,7 +602,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
}}
onBlur={saveComment}
onKeyDown={(event) => {
if (!event.shiftKey && event.key === KEYS.ENTER) {
if (!event.shiftKey && event.key === "Enter") {
event.preventDefault();
saveComment();
}
@@ -526,7 +635,12 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
</MainMenu.ItemCustom>
<MainMenu.DefaultItems.Help />
{excalidrawAPI && <MobileFooter excalidrawAPI={excalidrawAPI} />}
{excalidrawAPI && (
<MobileFooter
excalidrawLib={excalidrawLib}
excalidrawAPI={excalidrawAPI}
/>
)}
</MainMenu>
);
};
@@ -675,69 +789,7 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
</div>
</div>
<div className="excalidraw-wrapper">
<Excalidraw
excalidrawAPI={(api: ExcalidrawImperativeAPI) =>
setExcalidrawAPI(api)
}
initialData={initialStatePromiseRef.current.promise}
onChange={(elements, state) => {
console.info("Elements :", elements, "State : ", state);
}}
onPointerUpdate={(payload: {
pointer: { x: number; y: number };
button: "down" | "up";
pointersMap: Gesture["pointers"];
}) => setPointerData(payload)}
viewModeEnabled={viewModeEnabled}
zenModeEnabled={zenModeEnabled}
gridModeEnabled={gridModeEnabled}
theme={theme}
name="Custom name of drawing"
UIOptions={{
canvasActions: {
loadScene: false,
},
tools: { image: !disableImageTool },
}}
renderTopRightUI={renderTopRightUI}
onLinkOpen={onLinkOpen}
onPointerDown={onPointerDown}
onScrollChange={rerenderCommentIcons}
// allow all urls
validateEmbeddable={true}
>
{excalidrawAPI && (
<Footer>
<CustomFooter excalidrawAPI={excalidrawAPI} />
</Footer>
)}
<WelcomeScreen />
<Sidebar name="custom">
<Sidebar.Tabs>
<Sidebar.Header />
<Sidebar.Tab tab="one">Tab one!</Sidebar.Tab>
<Sidebar.Tab tab="two">Tab two!</Sidebar.Tab>
<Sidebar.TabTriggers>
<Sidebar.TabTrigger tab="one">One</Sidebar.TabTrigger>
<Sidebar.TabTrigger tab="two">Two</Sidebar.TabTrigger>
</Sidebar.TabTriggers>
</Sidebar.Tabs>
</Sidebar>
<Sidebar.Trigger
name="custom"
tab="one"
style={{
position: "absolute",
left: "50%",
transform: "translateX(-50%)",
bottom: "20px",
zIndex: 9999999999999999,
}}
>
Toggle Custom Sidebar
</Sidebar.Trigger>
{renderMenu()}
</Excalidraw>
{renderExcalidraw(children)}
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
{comment && renderComment()}
</div>

View File

@@ -1,6 +1,5 @@
import { ExcalidrawImperativeAPI } from "../../../types";
import { MIME_TYPES } from "../entry";
import { Button } from "../../../components/Button";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
const COMMENT_SVG = (
<svg
@@ -18,24 +17,28 @@ const COMMENT_SVG = (
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
</svg>
);
const CustomFooter = ({
excalidrawAPI,
excalidrawLib,
}: {
excalidrawAPI: ExcalidrawImperativeAPI;
excalidrawLib: typeof TExcalidraw;
}) => {
const { Button, MIME_TYPES } = excalidrawLib;
return (
<>
<Button
onSelect={() => alert("General Kenobi!")}
className="you are a bold one"
style={{ marginLeft: "1rem" }}
style={{ marginLeft: "1rem", width: "auto" }}
title="Hello there!"
>
{COMMENT_SVG}
Hit me
</Button>
<button
<Button
className="custom-element"
onClick={() => {
onSelect={() => {
excalidrawAPI?.setActiveTool({
type: "custom",
customType: "comment",
@@ -58,15 +61,10 @@ const CustomFooter = ({
)}`;
excalidrawAPI?.setCursor(`url(${url}), auto`);
}}
title="Comments!"
>
{COMMENT_SVG}
</button>
<button
className="custom-footer"
onClick={() => alert("This is dummy footer")}
>
custom footer
</button>
</Button>
</>
);
};

View File

@@ -0,0 +1,27 @@
import { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
import CustomFooter from "./CustomFooter";
import type * as TExcalidraw from "@excalidraw/excalidraw";
const MobileFooter = ({
excalidrawAPI,
excalidrawLib,
}: {
excalidrawAPI: ExcalidrawImperativeAPI;
excalidrawLib: typeof TExcalidraw;
}) => {
const { useDevice, Footer } = excalidrawLib;
const device = useDevice();
if (device.editor.isMobile) {
return (
<Footer>
<CustomFooter
excalidrawAPI={excalidrawAPI}
excalidrawLib={excalidrawLib}
/>
</Footer>
);
}
return null;
};
export default MobileFooter;

View File

@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { useState } from "react";
import "./ExampleSidebar.scss";
export default function Sidebar({ children }: { children: React.ReactNode }) {
const [open, setOpen] = useState(false);

View File

@@ -1,5 +1,5 @@
import { ExcalidrawElementSkeleton } from "../../../data/transform";
import { FileId } from "../../../element/types";
import type { ExcalidrawElementSkeleton } from "@excalidraw/excalidraw/data/transform";
import type { FileId } from "@excalidraw/excalidraw/element/types";
const elements: ExcalidrawElementSkeleton[] = [
{

View File

@@ -0,0 +1,13 @@
{
"name": "examples",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"@excalidraw/excalidraw": "*"
},
"devDependencies": {
"typescript": "^5"
}
}

View File

@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig"
}

View File

@@ -0,0 +1,146 @@
import { unstable_batchedUpdates } from "react-dom";
import { fileOpen as _fileOpen } from "browser-fs-access";
import type { MIME_TYPES } from "@excalidraw/excalidraw";
import { AbortError } from "../../packages/excalidraw/errors";
type FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, "binary">;
const INPUT_CHANGE_INTERVAL_MS = 500;
export type ResolvablePromise<T> = Promise<T> & {
resolve: [T] extends [undefined] ? (value?: T) => void : (value: T) => void;
reject: (error: Error) => void;
};
export const resolvablePromise = <T>() => {
let resolve!: any;
let reject!: any;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
(promise as any).resolve = resolve;
(promise as any).reject = reject;
return promise as ResolvablePromise<T>;
};
export const distance2d = (x1: number, y1: number, x2: number, y2: number) => {
const xd = x2 - x1;
const yd = y2 - y1;
return Math.hypot(xd, yd);
};
export const fileOpen = <M extends boolean | undefined = false>(opts: {
extensions?: FILE_EXTENSION[];
description: string;
multiple?: M;
}): Promise<M extends false | undefined ? File : File[]> => {
// an unsafe TS hack, alas not much we can do AFAIK
type RetType = M extends false | undefined ? File : File[];
const mimeTypes = opts.extensions?.reduce((mimeTypes, type) => {
mimeTypes.push(MIME_TYPES[type]);
return mimeTypes;
}, [] as string[]);
const extensions = opts.extensions?.reduce((acc, ext) => {
if (ext === "jpg") {
return acc.concat(".jpg", ".jpeg");
}
return acc.concat(`.${ext}`);
}, [] as string[]);
return _fileOpen({
description: opts.description,
extensions,
mimeTypes,
multiple: opts.multiple ?? false,
legacySetup: (resolve, reject, input) => {
const scheduleRejection = debounce(reject, INPUT_CHANGE_INTERVAL_MS);
const focusHandler = () => {
checkForFile();
document.addEventListener("keyup", scheduleRejection);
document.addEventListener("pointerup", scheduleRejection);
scheduleRejection();
};
const checkForFile = () => {
// this hack might not work when expecting multiple files
if (input.files?.length) {
const ret = opts.multiple ? [...input.files] : input.files[0];
resolve(ret as RetType);
}
};
requestAnimationFrame(() => {
window.addEventListener("focus", focusHandler);
});
const interval = window.setInterval(() => {
checkForFile();
}, INPUT_CHANGE_INTERVAL_MS);
return (rejectPromise) => {
clearInterval(interval);
scheduleRejection.cancel();
window.removeEventListener("focus", focusHandler);
document.removeEventListener("keyup", scheduleRejection);
document.removeEventListener("pointerup", scheduleRejection);
if (rejectPromise) {
// so that something is shown in console if we need to debug this
console.warn("Opening the file was canceled (legacy-fs).");
rejectPromise(new AbortError());
}
};
},
}) as Promise<RetType>;
};
export const debounce = <T extends any[]>(
fn: (...args: T) => void,
timeout: number,
) => {
let handle = 0;
let lastArgs: T | null = null;
const ret = (...args: T) => {
lastArgs = args;
clearTimeout(handle);
handle = window.setTimeout(() => {
lastArgs = null;
fn(...args);
}, timeout);
};
ret.flush = () => {
clearTimeout(handle);
if (lastArgs) {
const _lastArgs = lastArgs;
lastArgs = null;
fn(..._lastArgs);
}
};
ret.cancel = () => {
lastArgs = null;
clearTimeout(handle);
};
return ret;
};
export const withBatchedUpdates = <
TFunction extends ((event: any) => void) | (() => void),
>(
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
) =>
((event) => {
unstable_batchedUpdates(func as TFunction, event);
}) as TFunction;
/**
* barches React state updates and throttles the calls to a single call per
* animation frame
*/
export const withBatchedUpdatesThrottled = <
TFunction extends ((event: any) => void) | (() => void),
>(
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
) => {
// @ts-ignore
return throttleRAF<Parameters<TFunction>>(((event) => {
unstable_batchedUpdates(func, event);
}) as TFunction);
};

View File

@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3005) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@@ -0,0 +1,12 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
distDir: "build",
typescript: {
// The ts config doesn't work with `jsx: preserve" and if updated to `react-jsx` it gets ovewritten by next js throwing ts errors hence I am ignoring build errors until this is fixed.
ignoreBuildErrors: true,
},
// This is needed as in pages router the code for importing types throws error as its outside next js app
transpilePackages: ["../"],
};
module.exports = nextConfig;

View File

@@ -0,0 +1,25 @@
{
"name": "with-nextjs",
"version": "0.1.0",
"private": true,
"scripts": {
"build:workspace": "yarn workspace @excalidraw/excalidraw run build:esm",
"dev": "yarn build:workspace && next dev -p 3005",
"build": "yarn build:workspace && next build",
"start": "next start -p 3006",
"lint": "next lint"
},
"dependencies": {
"@excalidraw/excalidraw": "*",
"next": "14.1",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"path2d-polyfill": "2.0.1",
"typescript": "^5"
}
}

View File

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 197 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,11 @@
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,23 @@
import dynamic from "next/dynamic";
import "../common.scss";
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
// with ssr false
const ExcalidrawWithClientOnly = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<>
<a href="/excalidraw-in-pages">Switch to Pages router</a>
<h1 className="page-title">App Router</h1>
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
<ExcalidrawWithClientOnly />
</>
);
}

View File

@@ -0,0 +1,15 @@
* {
box-sizing: border-box;
font-family: sans-serif;
}
a {
color: #1c7ed6;
font-size: 20px;
text-decoration: none;
font-weight: 550;
}
.page-title {
text-align: center;
}

View File

@@ -0,0 +1,22 @@
"use client";
import * as excalidrawLib from "@excalidraw/excalidraw";
import { Excalidraw } from "@excalidraw/excalidraw";
import App from "../../components/App";
import "@excalidraw/excalidraw/index.css";
const ExcalidrawWrapper: React.FC = () => {
return (
<>
<App
appTitle={"Excalidraw with Nextjs Example"}
useCustom={(api: any, args?: any[]) => {}}
excalidrawLib={excalidrawLib}
>
<Excalidraw />
</App>
</>
);
};
export default ExcalidrawWrapper;

View File

@@ -0,0 +1,22 @@
import dynamic from "next/dynamic";
import "../common.scss";
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
// with ssr false
const Excalidraw = dynamic(
async () => (await import("../excalidrawWrapper")).default,
{
ssr: false,
},
);
export default function Page() {
return (
<>
<a href="/">Switch to App router</a>
<h1 className="page-title">Pages Router</h1>
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
<Excalidraw />
</>
);
}

View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
},
"forceConsistentCasingInFileNames": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "build/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,3 @@
{
"outputDirectory": "build"
}

View File

@@ -0,0 +1,252 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@excalidraw/excalidraw@workspace:^":
version "0.17.2"
resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.2.tgz#9a636a1e6bb3c88c5883347d3a7e75e9cce8ab96"
integrity sha512-7pqUWD8+mPjDhF4XxG3gw4rvE2JGaLW3Vss5UZfTbITPxAtFaGEc1K081bncitnaYhUwN9ENJE0i87QB3poDwQ==
"@next/env@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.0.4.tgz#d5cda0c4a862d70ae760e58c0cd96a8899a2e49a"
integrity sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==
"@next/swc-darwin-arm64@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz#27b1854c2cd04eb1d5e75081a1a792ad91526618"
integrity sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==
"@next/swc-darwin-x64@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz#9940c449e757d0ee50bb9e792d2600cc08a3eb3b"
integrity sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==
"@next/swc-linux-arm64-gnu@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz#0eafd27c8587f68ace7b4fa80695711a8434de21"
integrity sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==
"@next/swc-linux-arm64-musl@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz#2b0072adb213f36dada5394ea67d6e82069ae7dd"
integrity sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==
"@next/swc-linux-x64-gnu@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz#68c67d20ebc8e3f6ced6ff23a4ba2a679dbcec32"
integrity sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==
"@next/swc-linux-x64-musl@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz#67cd81b42fb2caf313f7992fcf6d978af55a1247"
integrity sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==
"@next/swc-win32-arm64-msvc@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz#be06585906b195d755ceda28f33c633e1443f1a3"
integrity sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==
"@next/swc-win32-ia32-msvc@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz#e76cabefa9f2d891599c3d85928475bd8d3f6600"
integrity sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==
"@next/swc-win32-x64-msvc@14.0.4":
version "14.0.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz#e74892f1a9ccf41d3bf5979ad6d3d77c07b9cba1"
integrity sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==
"@swc/helpers@0.5.2":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
dependencies:
tslib "^2.4.0"
"@types/node@^20":
version "20.11.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f"
integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
dependencies:
undici-types "~5.26.4"
"@types/prop-types@*":
version "15.7.11"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
"@types/react-dom@^18":
version "18.2.18"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd"
integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18":
version "18.2.47"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40"
integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/scheduler@*":
version "0.16.8"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
busboy@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"
caniuse-lite@^1.0.30001406:
version "1.0.30001576"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz#893be772cf8ee6056d6c1e2d07df365b9ec0a5c4"
integrity sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==
client-only@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
csstype@^3.0.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
glob-to-regexp@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
graceful-fs@^4.1.2, graceful-fs@^4.2.11:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
nanoid@^3.3.6:
version "3.3.7"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
next@14.0.4:
version "14.0.4"
resolved "https://registry.yarnpkg.com/next/-/next-14.0.4.tgz#bf00b6f835b20d10a5057838fa2dfced1d0d84dc"
integrity sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==
dependencies:
"@next/env" "14.0.4"
"@swc/helpers" "0.5.2"
busboy "1.6.0"
caniuse-lite "^1.0.30001406"
graceful-fs "^4.2.11"
postcss "8.4.31"
styled-jsx "5.1.1"
watchpack "2.4.0"
optionalDependencies:
"@next/swc-darwin-arm64" "14.0.4"
"@next/swc-darwin-x64" "14.0.4"
"@next/swc-linux-arm64-gnu" "14.0.4"
"@next/swc-linux-arm64-musl" "14.0.4"
"@next/swc-linux-x64-gnu" "14.0.4"
"@next/swc-linux-x64-musl" "14.0.4"
"@next/swc-win32-arm64-msvc" "14.0.4"
"@next/swc-win32-ia32-msvc" "14.0.4"
"@next/swc-win32-x64-msvc" "14.0.4"
path2d-polyfill@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz#24c554a738f42700d6961992bf5f1049672f2391"
integrity sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
postcss@8.4.31:
version "8.4.31"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
source-map-js "^1.0.2"
react-dom@^18:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
react@^18:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
streamsearch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
styled-jsx@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
dependencies:
client-only "0.0.1"
tslib@^2.4.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
typescript@^5:
version "5.3.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
undici-types@~5.26.4:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
watchpack@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
dependencies:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"

View File

@@ -12,18 +12,21 @@
<script>
window.name = "codesandbox";
</script>
<link rel="stylesheet" href="/dist/browser/dev/index.css" />
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
<script src="https://unpkg.com/react@18.2.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"></script>
<!-- This is so that we use the bundled excalidraw.development.js file instead
of the actual source code -->
<script src="./excalidraw.development.js"></script>
<script type="module">
import * as ExcalidrawLib from "@excalidraw/excalidraw";
<script src="./bundle.js"></script>
console.log(ExcalidrawLib);
window.ExcalidrawLib = ExcalidrawLib;
</script>
<script type="module" src="index.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,28 @@
import App from "../components/App";
import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import "@excalidraw/excalidraw/index.css";
declare global {
interface Window {
ExcalidrawLib: typeof TExcalidraw;
}
}
const rootElement = document.getElementById("root")!;
const root = createRoot(rootElement);
const { Excalidraw } = window.ExcalidrawLib;
root.render(
<StrictMode>
<App
appTitle={"Excalidraw Example"}
useCustom={(api: any, args?: any[]) => {}}
excalidrawLib={window.ExcalidrawLib}
>
<Excalidraw />
</App>
</StrictMode>,
);

View File

@@ -0,0 +1,19 @@
{
"name": "with-script-in-browser",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"@excalidraw/excalidraw": "*"
},
"devDependencies": {
"vite": "5.0.12",
"typescript": "^5"
},
"scripts": {
"start": "yarn workspace @excalidraw/excalidraw run build:esm && vite",
"build": "yarn workspace @excalidraw/excalidraw run build:esm && vite build",
"build:preview": "yarn build && vite preview --port 5002"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -0,0 +1,4 @@
{
"outputDirectory": "dist",
"installCommand": "yarn install"
}

View File

@@ -0,0 +1,11 @@
import { defineConfig } from "vite";
// https://vitejs.dev/config/
export default defineConfig({
server: {
port: 3001,
// open the browser
open: true,
},
publicDir: "public",
});

View File

@@ -0,0 +1,313 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@esbuild/aix-ppc64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz#2acd20be6d4f0458bc8c784103495ff24f13b1d3"
integrity sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==
"@esbuild/android-arm64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz#b45d000017385c9051a4f03e17078abb935be220"
integrity sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==
"@esbuild/android-arm@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.11.tgz#f46f55414e1c3614ac682b29977792131238164c"
integrity sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==
"@esbuild/android-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.11.tgz#bfc01e91740b82011ef503c48f548950824922b2"
integrity sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==
"@esbuild/darwin-arm64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz#533fb7f5a08c37121d82c66198263dcc1bed29bf"
integrity sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==
"@esbuild/darwin-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz#62f3819eff7e4ddc656b7c6815a31cf9a1e7d98e"
integrity sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==
"@esbuild/freebsd-arm64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz#d478b4195aa3ca44160272dab85ef8baf4175b4a"
integrity sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==
"@esbuild/freebsd-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz#7bdcc1917409178257ca6a1a27fe06e797ec18a2"
integrity sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==
"@esbuild/linux-arm64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz#58ad4ff11685fcc735d7ff4ca759ab18fcfe4545"
integrity sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==
"@esbuild/linux-arm@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz#ce82246d873b5534d34de1e5c1b33026f35e60e3"
integrity sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==
"@esbuild/linux-ia32@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz#cbae1f313209affc74b80f4390c4c35c6ab83fa4"
integrity sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==
"@esbuild/linux-loong64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz#5f32aead1c3ec8f4cccdb7ed08b166224d4e9121"
integrity sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==
"@esbuild/linux-mips64el@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz#38eecf1cbb8c36a616261de858b3c10d03419af9"
integrity sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==
"@esbuild/linux-ppc64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz#9c5725a94e6ec15b93195e5a6afb821628afd912"
integrity sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==
"@esbuild/linux-riscv64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz#2dc4486d474a2a62bbe5870522a9a600e2acb916"
integrity sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==
"@esbuild/linux-s390x@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz#4ad8567df48f7dd4c71ec5b1753b6f37561a65a8"
integrity sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==
"@esbuild/linux-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz#b7390c4d5184f203ebe7ddaedf073df82a658766"
integrity sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==
"@esbuild/netbsd-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz#d633c09492a1721377f3bccedb2d821b911e813d"
integrity sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==
"@esbuild/openbsd-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz#17388c76e2f01125bf831a68c03a7ffccb65d1a2"
integrity sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==
"@esbuild/sunos-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz#e320636f00bb9f4fdf3a80e548cb743370d41767"
integrity sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==
"@esbuild/win32-arm64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz#c778b45a496e90b6fc373e2a2bb072f1441fe0ee"
integrity sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==
"@esbuild/win32-ia32@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz#481a65fee2e5cce74ec44823e6b09ecedcc5194c"
integrity sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==
"@esbuild/win32-x64@0.19.11":
version "0.19.11"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04"
integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==
"@rollup/rollup-android-arm-eabi@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz#b752b6c88a14ccfcbdf3f48c577ccc3a7f0e66b9"
integrity sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==
"@rollup/rollup-android-arm64@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz#33757c3a448b9ef77b6f6292d8b0ec45c87e9c1a"
integrity sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==
"@rollup/rollup-darwin-arm64@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz#5234ba62665a3f443143bc8bcea9df2cc58f55fb"
integrity sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==
"@rollup/rollup-darwin-x64@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz#981256c054d3247b83313724938d606798a919d1"
integrity sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==
"@rollup/rollup-linux-arm-gnueabihf@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz#120678a5a2b3a283a548dbb4d337f9187a793560"
integrity sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==
"@rollup/rollup-linux-arm64-gnu@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz#c99d857e2372ece544b6f60b85058ad259f64114"
integrity sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==
"@rollup/rollup-linux-arm64-musl@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz#3064060f568a5718c2a06858cd6e6d24f2ff8632"
integrity sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==
"@rollup/rollup-linux-riscv64-gnu@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz#987d30b5d2b992fff07d055015991a57ff55fbad"
integrity sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==
"@rollup/rollup-linux-x64-gnu@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz#85946ee4d068bd12197aeeec2c6f679c94978a49"
integrity sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==
"@rollup/rollup-linux-x64-musl@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz#fe0b20f9749a60eb1df43d20effa96c756ddcbd4"
integrity sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==
"@rollup/rollup-win32-arm64-msvc@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz#422661ef0e16699a234465d15b2c1089ef963b2a"
integrity sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==
"@rollup/rollup-win32-ia32-msvc@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz#7b73a145891c202fbcc08759248983667a035d85"
integrity sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==
"@rollup/rollup-win32-x64-msvc@4.9.5":
version "4.9.5"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz#10491ccf4f63c814d4149e0316541476ea603602"
integrity sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==
"@types/estree@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
esbuild@^0.19.3:
version "0.19.11"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96"
integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==
optionalDependencies:
"@esbuild/aix-ppc64" "0.19.11"
"@esbuild/android-arm" "0.19.11"
"@esbuild/android-arm64" "0.19.11"
"@esbuild/android-x64" "0.19.11"
"@esbuild/darwin-arm64" "0.19.11"
"@esbuild/darwin-x64" "0.19.11"
"@esbuild/freebsd-arm64" "0.19.11"
"@esbuild/freebsd-x64" "0.19.11"
"@esbuild/linux-arm" "0.19.11"
"@esbuild/linux-arm64" "0.19.11"
"@esbuild/linux-ia32" "0.19.11"
"@esbuild/linux-loong64" "0.19.11"
"@esbuild/linux-mips64el" "0.19.11"
"@esbuild/linux-ppc64" "0.19.11"
"@esbuild/linux-riscv64" "0.19.11"
"@esbuild/linux-s390x" "0.19.11"
"@esbuild/linux-x64" "0.19.11"
"@esbuild/netbsd-x64" "0.19.11"
"@esbuild/openbsd-x64" "0.19.11"
"@esbuild/sunos-x64" "0.19.11"
"@esbuild/win32-arm64" "0.19.11"
"@esbuild/win32-ia32" "0.19.11"
"@esbuild/win32-x64" "0.19.11"
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
postcss@^8.4.32:
version "8.4.33"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.0"
source-map-js "^1.0.2"
react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
react@18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
rollup@^4.2.0:
version "4.9.5"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.5.tgz#62999462c90f4c8b5d7c38fc7161e63b29101b05"
integrity sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==
dependencies:
"@types/estree" "1.0.5"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.9.5"
"@rollup/rollup-android-arm64" "4.9.5"
"@rollup/rollup-darwin-arm64" "4.9.5"
"@rollup/rollup-darwin-x64" "4.9.5"
"@rollup/rollup-linux-arm-gnueabihf" "4.9.5"
"@rollup/rollup-linux-arm64-gnu" "4.9.5"
"@rollup/rollup-linux-arm64-musl" "4.9.5"
"@rollup/rollup-linux-riscv64-gnu" "4.9.5"
"@rollup/rollup-linux-x64-gnu" "4.9.5"
"@rollup/rollup-linux-x64-musl" "4.9.5"
"@rollup/rollup-win32-arm64-msvc" "4.9.5"
"@rollup/rollup-win32-ia32-msvc" "4.9.5"
"@rollup/rollup-win32-x64-msvc" "4.9.5"
fsevents "~2.3.2"
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
vite@5.0.6:
version "5.0.6"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.6.tgz#f9e13503a4c5ccd67312c67803dec921f3bdea7c"
integrity sha512-MD3joyAEBtV7QZPl2JVVUai6zHms3YOmLR+BpMzLlX2Yzjfcc4gTgNi09d/Rua3F4EtC8zdwPU8eQYyib4vVMQ==
dependencies:
esbuild "^0.19.3"
postcss "^8.4.32"
rollup "^4.2.0"
optionalDependencies:
fsevents "~2.3.3"

1122
excalidraw-app/App.tsx Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
import { useEffect, useState } from "react";
import { debounce, getVersion, nFormatter } from "../src/utils";
import { debounce, getVersion, nFormatter } from "../packages/excalidraw/utils";
import {
getElementsStorageSize,
getTotalStorageSize,
} from "./data/localStorage";
import { DEFAULT_VERSION } from "../src/constants";
import { t } from "../src/i18n";
import { copyTextToSystemClipboard } from "../src/clipboard";
import { NonDeletedExcalidrawElement } from "../src/element/types";
import { UIAppState } from "../src/types";
import { DEFAULT_VERSION } from "../packages/excalidraw/constants";
import { t } from "../packages/excalidraw/i18n";
import { copyTextToSystemClipboard } from "../packages/excalidraw/clipboard";
import { NonDeletedExcalidrawElement } from "../packages/excalidraw/element/types";
import { UIAppState } from "../packages/excalidraw/types";
type StorageSizes = { scene: number; total: number };

View File

@@ -15,11 +15,17 @@ export const FILE_CACHE_MAX_AGE_SEC = 31536000;
export const WS_EVENTS = {
SERVER_VOLATILE: "server-volatile-broadcast",
SERVER: "server-broadcast",
};
USER_FOLLOW_CHANGE: "user-follow",
USER_FOLLOW_ROOM_CHANGE: "user-follow-room-change",
} as const;
export enum WS_SCENE_EVENT_TYPES {
export enum WS_SUBTYPES {
INVALID_RESPONSE = "INVALID_RESPONSE",
INIT = "SCENE_INIT",
UPDATE = "SCENE_UPDATE",
MOUSE_LOCATION = "MOUSE_LOCATION",
IDLE_STATUS = "IDLE_STATUS",
USER_VISIBLE_SCENE_BOUNDS = "USER_VISIBLE_SCENE_BOUNDS",
}
export const FIREBASE_STORAGE_PREFIXES = {
@@ -33,10 +39,14 @@ export const STORAGE_KEYS = {
LOCAL_STORAGE_ELEMENTS: "excalidraw",
LOCAL_STORAGE_APP_STATE: "excalidraw-state",
LOCAL_STORAGE_COLLAB: "excalidraw-collab",
LOCAL_STORAGE_LIBRARY: "excalidraw-library",
LOCAL_STORAGE_THEME: "excalidraw-theme",
VERSION_DATA_STATE: "version-dataState",
VERSION_FILES: "version-files",
IDB_LIBRARY: "excalidraw-library",
// do not use apart from migrations
__LEGACY_LOCAL_STORAGE_LIBRARY: "excalidraw-library",
} as const;
export const COOKIES = {

View File

@@ -1,36 +1,42 @@
import throttle from "lodash.throttle";
import { PureComponent } from "react";
import { ExcalidrawImperativeAPI } from "../../src/types";
import { ErrorDialog } from "../../src/components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../src/constants";
import { ImportedDataState } from "../../src/data/types";
import {
ExcalidrawImperativeAPI,
SocketId,
} from "../../packages/excalidraw/types";
import { ErrorDialog } from "../../packages/excalidraw/components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../packages/excalidraw/constants";
import { ImportedDataState } from "../../packages/excalidraw/data/types";
import {
ExcalidrawElement,
InitializedExcalidrawImageElement,
} from "../../src/element/types";
OrderedExcalidrawElement,
} from "../../packages/excalidraw/element/types";
import {
getSceneVersion,
restoreElements,
} from "../../src/packages/excalidraw/index";
import { Collaborator, Gesture } from "../../src/types";
zoomToFitBounds,
} from "../../packages/excalidraw/index";
import { Collaborator, Gesture } from "../../packages/excalidraw/types";
import {
assertNever,
preventUnload,
resolvablePromise,
withBatchedUpdates,
} from "../../src/utils";
throttleRAF,
} from "../../packages/excalidraw/utils";
import {
CURSOR_SYNC_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,
FIREBASE_STORAGE_PREFIXES,
INITIAL_SCENE_UPDATE_TIMEOUT,
LOAD_IMAGES_TIMEOUT,
WS_SCENE_EVENT_TYPES,
WS_SUBTYPES,
SYNC_FULL_SCENE_INTERVAL_MS,
WS_EVENTS,
} from "../app_constants";
import {
generateCollaborationLinkData,
getCollaborationLink,
getCollabServer,
getSyncableElements,
SocketUpdateDataSource,
SyncableExcalidrawElement,
@@ -47,42 +53,52 @@ import {
saveUsernameToLocalStorage,
} from "../data/localStorage";
import Portal from "./Portal";
import RoomDialog from "./RoomDialog";
import { t } from "../../src/i18n";
import { UserIdleState } from "../../src/types";
import { IDLE_THRESHOLD, ACTIVE_THRESHOLD } from "../../src/constants";
import { t } from "../../packages/excalidraw/i18n";
import { UserIdleState } from "../../packages/excalidraw/types";
import {
IDLE_THRESHOLD,
ACTIVE_THRESHOLD,
} from "../../packages/excalidraw/constants";
import {
encodeFilesForUpload,
FileManager,
updateStaleImageStatuses,
} from "../data/FileManager";
import { AbortError } from "../../src/errors";
import { AbortError } from "../../packages/excalidraw/errors";
import {
isImageElement,
isInitializedImageElement,
} from "../../src/element/typeChecks";
import { newElementWith } from "../../src/element/mutateElement";
import {
ReconciledElements,
reconcileElements as _reconcileElements,
} from "./reconciliation";
import { decryptData } from "../../src/data/encryption";
} from "../../packages/excalidraw/element/typeChecks";
import { newElementWith } from "../../packages/excalidraw/element/mutateElement";
import { decryptData } from "../../packages/excalidraw/data/encryption";
import { resetBrowserStateVersions } from "../data/tabSync";
import { LocalData } from "../data/LocalData";
import { atom, useAtom } from "jotai";
import { atom } from "jotai";
import { appJotaiStore } from "../app-jotai";
import { Mutable, ValueOf } from "../../packages/excalidraw/utility-types";
import { getVisibleSceneBounds } from "../../packages/excalidraw/element/bounds";
import { withBatchedUpdates } from "../../packages/excalidraw/reactUtils";
import { collabErrorIndicatorAtom } from "./CollabError";
import {
ReconciledExcalidrawElement,
RemoteExcalidrawElement,
reconcileElements,
} from "../../packages/excalidraw/data/reconcile";
export const collabAPIAtom = atom<CollabAPI | null>(null);
export const collabDialogShownAtom = atom(false);
export const isCollaboratingAtom = atom(false);
export const isOfflineAtom = atom(false);
interface CollabState {
errorMessage: string;
errorMessage: string | null;
/** errors related to saving */
dialogNotifiedErrors: Record<string, boolean>;
username: string;
activeRoomLink: string;
activeRoomLink: string | null;
}
export const activeRoomLinkAtom = atom<string | null>(null);
type CollabInstance = InstanceType<typeof Collab>;
export interface CollabAPI {
@@ -93,32 +109,34 @@ export interface CollabAPI {
stopCollaboration: CollabInstance["stopCollaboration"];
syncElements: CollabInstance["syncElements"];
fetchImageFilesFromFirebase: CollabInstance["fetchImageFilesFromFirebase"];
setUsername: (username: string) => void;
setUsername: CollabInstance["setUsername"];
getUsername: CollabInstance["getUsername"];
getActiveRoomLink: CollabInstance["getActiveRoomLink"];
setCollabError: CollabInstance["setErrorDialog"];
}
interface PublicProps {
interface CollabProps {
excalidrawAPI: ExcalidrawImperativeAPI;
}
type Props = PublicProps & { modalIsShown: boolean };
class Collab extends PureComponent<Props, CollabState> {
class Collab extends PureComponent<CollabProps, CollabState> {
portal: Portal;
fileManager: FileManager;
excalidrawAPI: Props["excalidrawAPI"];
excalidrawAPI: CollabProps["excalidrawAPI"];
activeIntervalId: number | null;
idleTimeoutId: number | null;
private socketInitializationTimer?: number;
private lastBroadcastedOrReceivedSceneVersion: number = -1;
private collaborators = new Map<string, Collaborator>();
private collaborators = new Map<SocketId, Collaborator>();
constructor(props: Props) {
constructor(props: CollabProps) {
super(props);
this.state = {
errorMessage: "",
errorMessage: null,
dialogNotifiedErrors: {},
username: importUsernameFromLocalStorage() || "",
activeRoomLink: "",
activeRoomLink: null,
};
this.portal = new Portal(this);
this.fileManager = new FileManager({
@@ -151,12 +169,28 @@ class Collab extends PureComponent<Props, CollabState> {
this.idleTimeoutId = null;
}
private onUmmount: (() => void) | null = null;
componentDidMount() {
window.addEventListener(EVENT.BEFORE_UNLOAD, this.beforeUnload);
window.addEventListener("online", this.onOfflineStatusToggle);
window.addEventListener("offline", this.onOfflineStatusToggle);
window.addEventListener(EVENT.UNLOAD, this.onUnload);
const unsubOnUserFollow = this.excalidrawAPI.onUserFollow((payload) => {
this.portal.socket && this.portal.broadcastUserFollowed(payload);
});
const throttledRelayUserViewportBounds = throttleRAF(
this.relayVisibleSceneBounds,
);
const unsubOnScrollChange = this.excalidrawAPI.onScrollChange(() =>
throttledRelayUserViewportBounds(),
);
this.onUmmount = () => {
unsubOnUserFollow();
unsubOnScrollChange();
};
this.onOfflineStatusToggle();
const collabAPI: CollabAPI = {
@@ -167,6 +201,9 @@ class Collab extends PureComponent<Props, CollabState> {
fetchImageFilesFromFirebase: this.fetchImageFilesFromFirebase,
stopCollaboration: this.stopCollaboration,
setUsername: this.setUsername,
getUsername: this.getUsername,
getActiveRoomLink: this.getActiveRoomLink,
setCollabError: this.setErrorDialog,
};
appJotaiStore.set(collabAPIAtom, collabAPI);
@@ -204,6 +241,7 @@ class Collab extends PureComponent<Props, CollabState> {
window.clearTimeout(this.idleTimeoutId);
this.idleTimeoutId = null;
}
this.onUmmount?.();
}
isCollaborating = () => appJotaiStore.get(isCollaboratingAtom)!;
@@ -238,24 +276,39 @@ class Collab extends PureComponent<Props, CollabState> {
syncableElements: readonly SyncableExcalidrawElement[],
) => {
try {
const savedData = await saveToFirebase(
const storedElements = await saveToFirebase(
this.portal,
syncableElements,
this.excalidrawAPI.getAppState(),
);
if (this.isCollaborating() && savedData && savedData.reconciledElements) {
this.handleRemoteSceneUpdate(
this.reconcileElements(savedData.reconciledElements),
);
this.resetErrorIndicator();
if (this.isCollaborating() && storedElements) {
this.handleRemoteSceneUpdate(this._reconcileElements(storedElements));
}
} catch (error: any) {
this.setState({
// firestore doesn't return a specific error code when size exceeded
errorMessage: /is longer than.*?bytes/.test(error.message)
? t("errors.collabSaveFailed_sizeExceeded")
: t("errors.collabSaveFailed"),
});
const errorMessage = /is longer than.*?bytes/.test(error.message)
? t("errors.collabSaveFailed_sizeExceeded")
: t("errors.collabSaveFailed");
if (
!this.state.dialogNotifiedErrors[errorMessage] ||
!this.isCollaborating()
) {
this.setErrorDialog(errorMessage);
this.setState({
dialogNotifiedErrors: {
...this.state.dialogNotifiedErrors,
[errorMessage]: true,
},
});
}
if (this.isCollaborating()) {
this.setErrorIndicator(errorMessage);
}
console.error(error);
}
};
@@ -264,6 +317,7 @@ class Collab extends PureComponent<Props, CollabState> {
this.queueBroadcastAllElements.cancel();
this.queueSaveToFirebase.cancel();
this.loadImageFiles.cancel();
this.resetErrorIndicator(true);
this.saveCollabRoomToFirebase(
getSyncableElements(
@@ -313,9 +367,7 @@ class Collab extends PureComponent<Props, CollabState> {
this.fileManager.reset();
if (!opts?.isUnload) {
this.setIsCollaborating(false);
this.setState({
activeRoomLink: "",
});
this.setActiveRoomLink(null);
this.collaborators = new Map();
this.excalidrawAPI.updateScene({
collaborators: this.collaborators,
@@ -356,7 +408,7 @@ class Collab extends PureComponent<Props, CollabState> {
iv: Uint8Array,
encryptedData: ArrayBuffer,
decryptionKey: string,
) => {
): Promise<ValueOf<SocketUpdateDataSource>> => {
try {
const decrypted = await decryptData(iv, encryptedData, decryptionKey);
@@ -368,7 +420,7 @@ class Collab extends PureComponent<Props, CollabState> {
window.alert(t("alerts.decryptFailed"));
console.error(error);
return {
type: "INVALID_RESPONSE",
type: WS_SUBTYPES.INVALID_RESPONSE,
};
}
};
@@ -377,11 +429,11 @@ class Collab extends PureComponent<Props, CollabState> {
startCollaboration = async (
existingRoomLinkData: null | { roomId: string; roomKey: string },
): Promise<ImportedDataState | null> => {
) => {
if (!this.state.username) {
import("@excalidraw/random-username").then(({ getRandomUsername }) => {
const username = getRandomUsername();
this.onUsernameChange(username);
this.setUsername(username);
});
}
@@ -403,7 +455,11 @@ class Collab extends PureComponent<Props, CollabState> {
);
}
const scenePromise = resolvablePromise<ImportedDataState | null>();
// TODO: `ImportedDataState` type here seems abused
const scenePromise = resolvablePromise<
| (ImportedDataState & { elements: readonly OrderedExcalidrawElement[] })
| null
>();
this.setIsCollaborating(true);
LocalData.pauseSave("collaboration");
@@ -423,13 +479,9 @@ class Collab extends PureComponent<Props, CollabState> {
this.fallbackInitializationHandler = fallbackInitializationHandler;
try {
const socketServerData = await getCollabServer();
this.portal.socket = this.portal.open(
socketIOClient(socketServerData.url, {
transports: socketServerData.polling
? ["websocket", "polling"]
: ["websocket"],
socketIOClient(import.meta.env.VITE_APP_WS_SERVER_URL, {
transports: ["websocket", "polling"],
}),
roomId,
roomKey,
@@ -438,7 +490,7 @@ class Collab extends PureComponent<Props, CollabState> {
this.portal.socket.once("connect_error", fallbackInitializationHandler);
} catch (error: any) {
console.error(error);
this.setState({ errorMessage: error.message });
this.setErrorDialog(error.message);
return null;
}
@@ -484,13 +536,14 @@ class Collab extends PureComponent<Props, CollabState> {
);
switch (decryptedData.type) {
case "INVALID_RESPONSE":
case WS_SUBTYPES.INVALID_RESPONSE:
return;
case WS_SCENE_EVENT_TYPES.INIT: {
case WS_SUBTYPES.INIT: {
if (!this.portal.socketInitialized) {
this.initializeRoom({ fetchScene: false });
const remoteElements = decryptedData.payload.elements;
const reconciledElements = this.reconcileElements(remoteElements);
const reconciledElements =
this._reconcileElements(remoteElements);
this.handleRemoteSceneUpdate(reconciledElements, {
init: true,
});
@@ -502,41 +555,75 @@ class Collab extends PureComponent<Props, CollabState> {
}
break;
}
case WS_SCENE_EVENT_TYPES.UPDATE:
case WS_SUBTYPES.UPDATE:
this.handleRemoteSceneUpdate(
this.reconcileElements(decryptedData.payload.elements),
this._reconcileElements(decryptedData.payload.elements),
);
break;
case "MOUSE_LOCATION": {
case WS_SUBTYPES.MOUSE_LOCATION: {
const { pointer, button, username, selectedElementIds } =
decryptedData.payload;
const socketId: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["socketId"] =
decryptedData.payload.socketId ||
// @ts-ignore legacy, see #2094 (#2097)
decryptedData.payload.socketID;
const collaborators = new Map(this.collaborators);
const user = collaborators.get(socketId) || {}!;
user.pointer = pointer;
user.button = button;
user.selectedElementIds = selectedElementIds;
user.username = username;
collaborators.set(socketId, user);
this.updateCollaborator(socketId, {
pointer,
button,
selectedElementIds,
username,
});
break;
}
case WS_SUBTYPES.USER_VISIBLE_SCENE_BOUNDS: {
const { sceneBounds, socketId } = decryptedData.payload;
const appState = this.excalidrawAPI.getAppState();
// we're not following the user
// (shouldn't happen, but could be late message or bug upstream)
if (appState.userToFollow?.socketId !== socketId) {
console.warn(
`receiving remote client's (from ${socketId}) viewport bounds even though we're not subscribed to it!`,
);
return;
}
// cross-follow case, ignore updates in this case
if (
appState.userToFollow &&
appState.followedBy.has(appState.userToFollow.socketId)
) {
return;
}
this.excalidrawAPI.updateScene({
collaborators,
appState: zoomToFitBounds({
appState,
bounds: sceneBounds,
fitToViewport: true,
viewportZoomFactor: 1,
}).appState,
});
break;
}
case WS_SUBTYPES.IDLE_STATUS: {
const { userState, socketId, username } = decryptedData.payload;
this.updateCollaborator(socketId, {
userState,
username,
});
break;
}
case "IDLE_STATUS": {
const { userState, socketId, username } = decryptedData.payload;
const collaborators = new Map(this.collaborators);
const user = collaborators.get(socketId) || {}!;
user.userState = userState;
user.username = username;
this.excalidrawAPI.updateScene({
collaborators,
});
break;
default: {
assertNever(decryptedData, null);
}
}
},
@@ -553,11 +640,20 @@ class Collab extends PureComponent<Props, CollabState> {
scenePromise.resolve(sceneData);
});
this.portal.socket.on(
WS_EVENTS.USER_FOLLOW_ROOM_CHANGE,
(followedBy: SocketId[]) => {
this.excalidrawAPI.updateScene({
appState: { followedBy: new Set(followedBy) },
});
this.relayVisibleSceneBounds({ force: true });
},
);
this.initializeIdleDetector();
this.setState({
activeRoomLink: window.location.href,
});
this.setActiveRoomLink(window.location.href);
return scenePromise;
};
@@ -609,17 +705,15 @@ class Collab extends PureComponent<Props, CollabState> {
return null;
};
private reconcileElements = (
private _reconcileElements = (
remoteElements: readonly ExcalidrawElement[],
): ReconciledElements => {
): ReconciledExcalidrawElement[] => {
const localElements = this.getSceneElementsIncludingDeleted();
const appState = this.excalidrawAPI.getAppState();
remoteElements = restoreElements(remoteElements, null);
const reconciledElements = _reconcileElements(
const restoredRemoteElements = restoreElements(remoteElements, null);
const reconciledElements = reconcileElements(
localElements,
remoteElements,
restoredRemoteElements as RemoteExcalidrawElement[],
appState,
);
@@ -650,7 +744,7 @@ class Collab extends PureComponent<Props, CollabState> {
}, LOAD_IMAGES_TIMEOUT);
private handleRemoteSceneUpdate = (
elements: ReconciledElements,
elements: ReconciledExcalidrawElement[],
{ init = false }: { init?: boolean } = {},
) => {
this.excalidrawAPI.updateScene({
@@ -721,20 +815,39 @@ class Collab extends PureComponent<Props, CollabState> {
document.addEventListener(EVENT.VISIBILITY_CHANGE, this.onVisibilityChange);
};
setCollaborators(sockets: string[]) {
setCollaborators(sockets: SocketId[]) {
const collaborators: InstanceType<typeof Collab>["collaborators"] =
new Map();
for (const socketId of sockets) {
if (this.collaborators.has(socketId)) {
collaborators.set(socketId, this.collaborators.get(socketId)!);
} else {
collaborators.set(socketId, {});
}
collaborators.set(
socketId,
Object.assign({}, this.collaborators.get(socketId), {
isCurrentUser: socketId === this.portal.socket?.id,
}),
);
}
this.collaborators = collaborators;
this.excalidrawAPI.updateScene({ collaborators });
}
updateCollaborator = (socketId: SocketId, updates: Partial<Collaborator>) => {
const collaborators = new Map(this.collaborators);
const user: Mutable<Collaborator> = Object.assign(
{},
collaborators.get(socketId),
updates,
{
isCurrentUser: socketId === this.portal.socket?.id,
},
);
collaborators.set(socketId, user);
this.collaborators = collaborators;
this.excalidrawAPI.updateScene({
collaborators,
});
};
public setLastBroadcastedOrReceivedSceneVersion = (version: number) => {
this.lastBroadcastedOrReceivedSceneVersion = version;
};
@@ -760,29 +873,42 @@ class Collab extends PureComponent<Props, CollabState> {
CURSOR_SYNC_TIMEOUT,
);
relayVisibleSceneBounds = (props?: { force: boolean }) => {
const appState = this.excalidrawAPI.getAppState();
if (this.portal.socket && (appState.followedBy.size > 0 || props?.force)) {
this.portal.broadcastVisibleSceneBounds(
{
sceneBounds: getVisibleSceneBounds(appState),
},
`follow@${this.portal.socket.id}`,
);
}
};
onIdleStateChange = (userState: UserIdleState) => {
this.portal.broadcastIdleChange(userState);
};
broadcastElements = (elements: readonly ExcalidrawElement[]) => {
broadcastElements = (elements: readonly OrderedExcalidrawElement[]) => {
if (
getSceneVersion(elements) >
this.getLastBroadcastedOrReceivedSceneVersion()
) {
this.portal.broadcastScene(WS_SCENE_EVENT_TYPES.UPDATE, elements, false);
this.portal.broadcastScene(WS_SUBTYPES.UPDATE, elements, false);
this.lastBroadcastedOrReceivedSceneVersion = getSceneVersion(elements);
this.queueBroadcastAllElements();
}
};
syncElements = (elements: readonly ExcalidrawElement[]) => {
syncElements = (elements: readonly OrderedExcalidrawElement[]) => {
this.broadcastElements(elements);
this.queueSaveToFirebase();
};
queueBroadcastAllElements = throttle(() => {
this.portal.broadcastScene(
WS_SCENE_EVENT_TYPES.UPDATE,
WS_SUBTYPES.UPDATE,
this.excalidrawAPI.getSceneElementsIncludingDeleted(),
true,
);
@@ -808,41 +934,49 @@ class Collab extends PureComponent<Props, CollabState> {
{ leading: false },
);
handleClose = () => {
appJotaiStore.set(collabDialogShownAtom, false);
};
setUsername = (username: string) => {
this.setState({ username });
};
onUsernameChange = (username: string) => {
this.setUsername(username);
saveUsernameToLocalStorage(username);
};
render() {
const { username, errorMessage, activeRoomLink } = this.state;
getUsername = () => this.state.username;
const { modalIsShown } = this.props;
setActiveRoomLink = (activeRoomLink: string | null) => {
this.setState({ activeRoomLink });
appJotaiStore.set(activeRoomLinkAtom, activeRoomLink);
};
getActiveRoomLink = () => this.state.activeRoomLink;
setErrorIndicator = (errorMessage: string | null) => {
appJotaiStore.set(collabErrorIndicatorAtom, {
message: errorMessage,
nonce: Date.now(),
});
};
resetErrorIndicator = (resetDialogNotifiedErrors = false) => {
appJotaiStore.set(collabErrorIndicatorAtom, { message: null, nonce: 0 });
if (resetDialogNotifiedErrors) {
this.setState({
dialogNotifiedErrors: {},
});
}
};
setErrorDialog = (errorMessage: string | null) => {
this.setState({
errorMessage,
});
};
render() {
const { errorMessage } = this.state;
return (
<>
{modalIsShown && (
<RoomDialog
handleClose={this.handleClose}
activeRoomLink={activeRoomLink}
username={username}
onUsernameChange={this.onUsernameChange}
onRoomCreate={() => this.startCollaboration(null)}
onRoomDestroy={this.stopCollaboration}
setErrorMessage={(errorMessage) => {
this.setState({ errorMessage });
}}
/>
)}
{errorMessage && (
<ErrorDialog onClose={() => this.setState({ errorMessage: "" })}>
{errorMessage != null && (
<ErrorDialog onClose={() => this.setErrorDialog(null)}>
{errorMessage}
</ErrorDialog>
)}
@@ -861,11 +995,6 @@ if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
window.collab = window.collab || ({} as Window["collab"]);
}
const _Collab: React.FC<PublicProps> = (props) => {
const [collabDialogShown] = useAtom(collabDialogShownAtom);
return <Collab {...props} modalIsShown={collabDialogShown} />;
};
export default _Collab;
export default Collab;
export type TCollabClass = Collab;

View File

@@ -0,0 +1,35 @@
@import "../../packages/excalidraw/css/variables.module.scss";
.excalidraw {
.collab-errors-button {
width: 26px;
height: 26px;
margin-inline-end: 1rem;
color: var(--color-danger);
flex-shrink: 0;
}
.collab-errors-button-shake {
animation: strong-shake 0.15s 6;
}
@keyframes strong-shake {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(10deg);
}
50% {
transform: rotate(0eg);
}
75% {
transform: rotate(-10deg);
}
100% {
transform: rotate(0deg);
}
}
}

View File

@@ -0,0 +1,54 @@
import { Tooltip } from "../../packages/excalidraw/components/Tooltip";
import { warning } from "../../packages/excalidraw/components/icons";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
import "./CollabError.scss";
import { atom } from "jotai";
type ErrorIndicator = {
message: string | null;
/** used to rerun the useEffect responsible for animation */
nonce: number;
};
export const collabErrorIndicatorAtom = atom<ErrorIndicator>({
message: null,
nonce: 0,
});
const CollabError = ({ collabError }: { collabError: ErrorIndicator }) => {
const [isAnimating, setIsAnimating] = useState(false);
const clearAnimationRef = useRef<string | number | NodeJS.Timeout>();
useEffect(() => {
setIsAnimating(true);
clearAnimationRef.current = setTimeout(() => {
setIsAnimating(false);
}, 1000);
return () => {
clearTimeout(clearAnimationRef.current);
};
}, [collabError.message, collabError.nonce]);
if (!collabError.message) {
return null;
}
return (
<Tooltip label={collabError.message} long={true}>
<div
className={clsx("collab-errors-button", {
"collab-errors-button-shake": isAnimating,
})}
>
{warning}
</div>
</Tooltip>
);
};
CollabError.displayName = "CollabError";
export default CollabError;

View File

@@ -2,27 +2,27 @@ import {
isSyncableElement,
SocketUpdateData,
SocketUpdateDataSource,
SyncableExcalidrawElement,
} from "../data";
import { TCollabClass } from "./Collab";
import { ExcalidrawElement } from "../../src/element/types";
import { OrderedExcalidrawElement } from "../../packages/excalidraw/element/types";
import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants";
import {
WS_EVENTS,
FILE_UPLOAD_TIMEOUT,
WS_SCENE_EVENT_TYPES,
} from "../app_constants";
import { UserIdleState } from "../../src/types";
import { trackEvent } from "../../src/analytics";
OnUserFollowedPayload,
SocketId,
UserIdleState,
} from "../../packages/excalidraw/types";
import { trackEvent } from "../../packages/excalidraw/analytics";
import throttle from "lodash.throttle";
import { newElementWith } from "../../src/element/mutateElement";
import { BroadcastedExcalidrawElement } from "./reconciliation";
import { encryptData } from "../../src/data/encryption";
import { PRECEDING_ELEMENT_KEY } from "../../src/constants";
import { newElementWith } from "../../packages/excalidraw/element/mutateElement";
import { encryptData } from "../../packages/excalidraw/data/encryption";
import type { Socket } from "socket.io-client";
class Portal {
collab: TCollabClass;
socket: SocketIOClient.Socket | null = null;
socket: Socket | null = null;
socketInitialized: boolean = false; // we don't want the socket to emit any updates until it is fully initialized
roomId: string | null = null;
roomKey: string | null = null;
@@ -32,7 +32,7 @@ class Portal {
this.collab = collab;
}
open(socket: SocketIOClient.Socket, id: string, key: string) {
open(socket: Socket, id: string, key: string) {
this.socket = socket;
this.roomId = id;
this.roomKey = key;
@@ -46,12 +46,12 @@ class Portal {
});
this.socket.on("new-user", async (_socketId: string) => {
this.broadcastScene(
WS_SCENE_EVENT_TYPES.INIT,
WS_SUBTYPES.INIT,
this.collab.getSceneElementsIncludingDeleted(),
/* syncAll */ true,
);
});
this.socket.on("room-user-change", (clients: string[]) => {
this.socket.on("room-user-change", (clients: SocketId[]) => {
this.collab.setCollaborators(clients);
});
@@ -83,6 +83,7 @@ class Portal {
async _broadcastSocketData(
data: SocketUpdateData,
volatile: boolean = false,
roomId?: string,
) {
if (this.isOpen()) {
const json = JSON.stringify(data);
@@ -91,7 +92,7 @@ class Portal {
this.socket?.emit(
volatile ? WS_EVENTS.SERVER_VOLATILE : WS_EVENTS.SERVER,
this.roomId,
roomId ?? this.roomId,
encryptedBuffer,
iv,
);
@@ -130,36 +131,28 @@ class Portal {
}, FILE_UPLOAD_TIMEOUT);
broadcastScene = async (
updateType: WS_SCENE_EVENT_TYPES.INIT | WS_SCENE_EVENT_TYPES.UPDATE,
allElements: readonly ExcalidrawElement[],
updateType: WS_SUBTYPES.INIT | WS_SUBTYPES.UPDATE,
elements: readonly OrderedExcalidrawElement[],
syncAll: boolean,
) => {
if (updateType === WS_SCENE_EVENT_TYPES.INIT && !syncAll) {
if (updateType === WS_SUBTYPES.INIT && !syncAll) {
throw new Error("syncAll must be true when sending SCENE.INIT");
}
// sync out only the elements we think we need to to save bandwidth.
// periodically we'll resync the whole thing to make sure no one diverges
// due to a dropped message (server goes down etc).
const syncableElements = allElements.reduce(
(acc, element: BroadcastedExcalidrawElement, idx, elements) => {
if (
(syncAll ||
!this.broadcastedElementVersions.has(element.id) ||
element.version >
this.broadcastedElementVersions.get(element.id)!) &&
isSyncableElement(element)
) {
acc.push({
...element,
// z-index info for the reconciler
[PRECEDING_ELEMENT_KEY]: idx === 0 ? "^" : elements[idx - 1]?.id,
});
}
return acc;
},
[] as BroadcastedExcalidrawElement[],
);
const syncableElements = elements.reduce((acc, element) => {
if (
(syncAll ||
!this.broadcastedElementVersions.has(element.id) ||
element.version > this.broadcastedElementVersions.get(element.id)!) &&
isSyncableElement(element)
) {
acc.push(element);
}
return acc;
}, [] as SyncableExcalidrawElement[]);
const data: SocketUpdateDataSource[typeof updateType] = {
type: updateType,
@@ -183,9 +176,9 @@ class Portal {
broadcastIdleChange = (userState: UserIdleState) => {
if (this.socket?.id) {
const data: SocketUpdateDataSource["IDLE_STATUS"] = {
type: "IDLE_STATUS",
type: WS_SUBTYPES.IDLE_STATUS,
payload: {
socketId: this.socket.id,
socketId: this.socket.id as SocketId,
userState,
username: this.collab.state.username,
},
@@ -203,9 +196,9 @@ class Portal {
}) => {
if (this.socket?.id) {
const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
type: "MOUSE_LOCATION",
type: WS_SUBTYPES.MOUSE_LOCATION,
payload: {
socketId: this.socket.id,
socketId: this.socket.id as SocketId,
pointer: payload.pointer,
button: payload.button || "up",
selectedElementIds:
@@ -213,12 +206,43 @@ class Portal {
username: this.collab.state.username,
},
};
return this._broadcastSocketData(
data as SocketUpdateData,
true, // volatile
);
}
};
broadcastVisibleSceneBounds = (
payload: {
sceneBounds: SocketUpdateDataSource["USER_VISIBLE_SCENE_BOUNDS"]["payload"]["sceneBounds"];
},
roomId: string,
) => {
if (this.socket?.id) {
const data: SocketUpdateDataSource["USER_VISIBLE_SCENE_BOUNDS"] = {
type: WS_SUBTYPES.USER_VISIBLE_SCENE_BOUNDS,
payload: {
socketId: this.socket.id as SocketId,
username: this.collab.state.username,
sceneBounds: payload.sceneBounds,
},
};
return this._broadcastSocketData(
data as SocketUpdateData,
true, // volatile
roomId,
);
}
};
broadcastUserFollowed = (payload: OnUserFollowedPayload) => {
if (this.socket?.id) {
this.socket.emit(WS_EVENTS.USER_FOLLOW_CHANGE, payload);
}
};
}
export default Portal;

View File

@@ -1,13 +1,13 @@
import { useRef, useState } from "react";
import * as Popover from "@radix-ui/react-popover";
import { copyTextToSystemClipboard } from "../../src/clipboard";
import { trackEvent } from "../../src/analytics";
import { getFrame } from "../../src/utils";
import { useI18n } from "../../src/i18n";
import { KEYS } from "../../src/keys";
import { copyTextToSystemClipboard } from "../../packages/excalidraw/clipboard";
import { trackEvent } from "../../packages/excalidraw/analytics";
import { getFrame } from "../../packages/excalidraw/utils";
import { useI18n } from "../../packages/excalidraw/i18n";
import { KEYS } from "../../packages/excalidraw/keys";
import { Dialog } from "../../src/components/Dialog";
import { Dialog } from "../../packages/excalidraw/components/Dialog";
import {
copyIcon,
playerPlayIcon,
@@ -16,11 +16,11 @@ import {
shareIOS,
shareWindows,
tablerCheckIcon,
} from "../../src/components/icons";
import { TextField } from "../../src/components/TextField";
import { FilledButton } from "../../src/components/FilledButton";
} from "../../packages/excalidraw/components/icons";
import { TextField } from "../../packages/excalidraw/components/TextField";
import { FilledButton } from "../../packages/excalidraw/components/FilledButton";
import { ReactComponent as CollabImage } from "../../src/assets/lock.svg";
import { ReactComponent as CollabImage } from "../../packages/excalidraw/assets/lock.svg";
import "./RoomDialog.scss";
const getShareIcon = () => {
@@ -65,19 +65,18 @@ export const RoomModal = ({
const copyRoomLink = async () => {
try {
await copyTextToSystemClipboard(activeRoomLink);
setJustCopied(true);
if (timerRef.current) {
window.clearTimeout(timerRef.current);
}
timerRef.current = window.setTimeout(() => {
setJustCopied(false);
}, 3000);
} catch (error: any) {
setErrorMessage(error.message);
} catch (e) {
setErrorMessage(t("errors.copyToSystemClipboardFailed"));
}
setJustCopied(true);
if (timerRef.current) {
window.clearTimeout(timerRef.current);
}
timerRef.current = window.setTimeout(() => {
setJustCopied(false);
}, 3000);
ref.current?.select();
};
@@ -120,7 +119,7 @@ export const RoomModal = ({
size="large"
variant="icon"
label="Share"
startIcon={getShareIcon()}
icon={getShareIcon()}
className="RoomDialog__active__share"
onClick={shareRoomLink}
/>
@@ -130,7 +129,7 @@ export const RoomModal = ({
<FilledButton
size="large"
label="Copy link"
startIcon={copyIcon}
icon={copyIcon}
onClick={copyRoomLink}
/>
</Popover.Trigger>
@@ -166,7 +165,7 @@ export const RoomModal = ({
variant="outlined"
color="danger"
label={t("roomDialog.button_stopSession")}
startIcon={playerStopFilledIcon}
icon={playerStopFilledIcon}
onClick={() => {
trackEvent("share", "room closed");
onRoomDestroy();
@@ -195,7 +194,7 @@ export const RoomModal = ({
<FilledButton
size="large"
label={t("roomDialog.button_startSession")}
startIcon={playerPlayIcon}
icon={playerPlayIcon}
onClick={() => {
trackEvent("share", "room creation", `ui (${getFrame()})`);
onRoomCreate();

View File

@@ -1,154 +0,0 @@
import { PRECEDING_ELEMENT_KEY } from "../../src/constants";
import { ExcalidrawElement } from "../../src/element/types";
import { AppState } from "../../src/types";
import { arrayToMapWithIndex } from "../../src/utils";
export type ReconciledElements = readonly ExcalidrawElement[] & {
_brand: "reconciledElements";
};
export type BroadcastedExcalidrawElement = ExcalidrawElement & {
[PRECEDING_ELEMENT_KEY]?: string;
};
const shouldDiscardRemoteElement = (
localAppState: AppState,
local: ExcalidrawElement | undefined,
remote: BroadcastedExcalidrawElement,
): boolean => {
if (
local &&
// local element is being edited
(local.id === localAppState.editingElement?.id ||
local.id === localAppState.resizingElement?.id ||
local.id === localAppState.draggingElement?.id ||
// local element is newer
local.version > remote.version ||
// resolve conflicting edits deterministically by taking the one with
// the lowest versionNonce
(local.version === remote.version &&
local.versionNonce < remote.versionNonce))
) {
return true;
}
return false;
};
export const reconcileElements = (
localElements: readonly ExcalidrawElement[],
remoteElements: readonly BroadcastedExcalidrawElement[],
localAppState: AppState,
): ReconciledElements => {
const localElementsData =
arrayToMapWithIndex<ExcalidrawElement>(localElements);
const reconciledElements: ExcalidrawElement[] = localElements.slice();
const duplicates = new WeakMap<ExcalidrawElement, true>();
let cursor = 0;
let offset = 0;
let remoteElementIdx = -1;
for (const remoteElement of remoteElements) {
remoteElementIdx++;
const local = localElementsData.get(remoteElement.id);
if (shouldDiscardRemoteElement(localAppState, local?.[0], remoteElement)) {
if (remoteElement[PRECEDING_ELEMENT_KEY]) {
delete remoteElement[PRECEDING_ELEMENT_KEY];
}
continue;
}
// Mark duplicate for removal as it'll be replaced with the remote element
if (local) {
// Unless the remote and local elements are the same element in which case
// we need to keep it as we'd otherwise discard it from the resulting
// array.
if (local[0] === remoteElement) {
continue;
}
duplicates.set(local[0], true);
}
// parent may not be defined in case the remote client is running an older
// excalidraw version
const parent =
remoteElement[PRECEDING_ELEMENT_KEY] ||
remoteElements[remoteElementIdx - 1]?.id ||
null;
if (parent != null) {
delete remoteElement[PRECEDING_ELEMENT_KEY];
// ^ indicates the element is the first in elements array
if (parent === "^") {
offset++;
if (cursor === 0) {
reconciledElements.unshift(remoteElement);
localElementsData.set(remoteElement.id, [
remoteElement,
cursor - offset,
]);
} else {
reconciledElements.splice(cursor + 1, 0, remoteElement);
localElementsData.set(remoteElement.id, [
remoteElement,
cursor + 1 - offset,
]);
cursor++;
}
} else {
let idx = localElementsData.has(parent)
? localElementsData.get(parent)![1]
: null;
if (idx != null) {
idx += offset;
}
if (idx != null && idx >= cursor) {
reconciledElements.splice(idx + 1, 0, remoteElement);
offset++;
localElementsData.set(remoteElement.id, [
remoteElement,
idx + 1 - offset,
]);
cursor = idx + 1;
} else if (idx != null) {
reconciledElements.splice(cursor + 1, 0, remoteElement);
offset++;
localElementsData.set(remoteElement.id, [
remoteElement,
cursor + 1 - offset,
]);
cursor++;
} else {
reconciledElements.push(remoteElement);
localElementsData.set(remoteElement.id, [
remoteElement,
reconciledElements.length - 1 - offset,
]);
}
}
// no parent z-index information, local element exists → replace in place
} else if (local) {
reconciledElements[local[1]] = remoteElement;
localElementsData.set(remoteElement.id, [remoteElement, local[1]]);
// otherwise push to the end
} else {
reconciledElements.push(remoteElement);
localElementsData.set(remoteElement.id, [
remoteElement,
reconciledElements.length - 1 - offset,
]);
}
}
const ret: readonly ExcalidrawElement[] = reconciledElements.filter(
(element) => !duplicates.has(element),
);
return ret as ReconciledElements;
};

View File

@@ -1,5 +1,5 @@
import React from "react";
import { Footer } from "../../src/packages/excalidraw/index";
import { Footer } from "../../packages/excalidraw/index";
import { EncryptedIcon } from "./EncryptedIcon";
import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink";
import { isExcalidrawPlusSignedUser } from "../app_constants";

View File

@@ -1,12 +1,19 @@
import React from "react";
import { PlusPromoIcon } from "../../src/components/icons";
import { MainMenu } from "../../src/packages/excalidraw/index";
import {
arrowBarToLeftIcon,
ExcalLogo,
} from "../../packages/excalidraw/components/icons";
import { Theme } from "../../packages/excalidraw/element/types";
import { MainMenu } from "../../packages/excalidraw/index";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { LanguageList } from "./LanguageList";
export const AppMainMenu: React.FC<{
setCollabDialogShown: (toggle: boolean) => any;
onCollabDialogOpen: () => any;
isCollaborating: boolean;
isCollabEnabled: boolean;
theme: Theme | "system";
setTheme: (theme: Theme | "system") => void;
}> = React.memo((props) => {
return (
<MainMenu>
@@ -17,25 +24,38 @@ export const AppMainMenu: React.FC<{
{props.isCollabEnabled && (
<MainMenu.DefaultItems.LiveCollaborationTrigger
isCollaborating={props.isCollaborating}
onSelect={() => props.setCollabDialogShown(true)}
onSelect={() => props.onCollabDialogOpen()}
/>
)}
<MainMenu.DefaultItems.CommandPalette className="highlighted" />
<MainMenu.DefaultItems.Help />
<MainMenu.DefaultItems.ClearCanvas />
<MainMenu.Separator />
<MainMenu.ItemLink
icon={PlusPromoIcon}
icon={ExcalLogo}
href={`${
import.meta.env.VITE_APP_PLUS_LP
import.meta.env.VITE_APP_PLUS_APP
}/plus?utm_source=excalidraw&utm_medium=app&utm_content=hamburger`}
className="ExcalidrawPlus"
className=""
>
Excalidraw+
</MainMenu.ItemLink>
<MainMenu.DefaultItems.Socials />
<MainMenu.ItemLink
icon={arrowBarToLeftIcon}
href={`${import.meta.env.VITE_APP_PLUS_APP}${
isExcalidrawPlusSignedUser ? "" : "/sign-up"
}?utm_source=signin&utm_medium=app&utm_content=hamburger`}
className="highlighted"
>
{isExcalidrawPlusSignedUser ? "Sign in" : "Sign up"}
</MainMenu.ItemLink>
<MainMenu.Separator />
<MainMenu.DefaultItems.ToggleTheme />
<MainMenu.DefaultItems.ToggleTheme
allowSystemTheme
theme={props.theme}
onSelect={props.setTheme}
/>
<MainMenu.ItemCustom>
<LanguageList style={{ width: "100%" }} />
</MainMenu.ItemCustom>

View File

@@ -1,12 +1,12 @@
import React from "react";
import { PlusPromoIcon } from "../../src/components/icons";
import { useI18n } from "../../src/i18n";
import { WelcomeScreen } from "../../src/packages/excalidraw/index";
import { arrowBarToLeftIcon } from "../../packages/excalidraw/components/icons";
import { useI18n } from "../../packages/excalidraw/i18n";
import { WelcomeScreen } from "../../packages/excalidraw/index";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { POINTER_EVENTS } from "../../src/constants";
import { POINTER_EVENTS } from "../../packages/excalidraw/constants";
export const AppWelcomeScreen: React.FC<{
setCollabDialogShown: (toggle: boolean) => any;
onCollabDialogOpen: () => any;
isCollabEnabled: boolean;
}> = React.memo((props) => {
const { t } = useI18n();
@@ -52,7 +52,7 @@ export const AppWelcomeScreen: React.FC<{
<WelcomeScreen.Center.MenuItemHelp />
{props.isCollabEnabled && (
<WelcomeScreen.Center.MenuItemLiveCollaborationTrigger
onSelect={() => props.setCollabDialogShown(true)}
onSelect={() => props.onCollabDialogOpen()}
/>
)}
{!isExcalidrawPlusSignedUser && (
@@ -61,9 +61,9 @@ export const AppWelcomeScreen: React.FC<{
import.meta.env.VITE_APP_PLUS_LP
}/plus?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenGuest`}
shortcut={null}
icon={PlusPromoIcon}
icon={arrowBarToLeftIcon}
>
Try Excalidraw Plus!
Sign up
</WelcomeScreen.Center.MenuItemLink>
)}
</WelcomeScreen.Center.Menu>

View File

@@ -1,6 +1,6 @@
import { shield } from "../../src/components/icons";
import { Tooltip } from "../../src/components/Tooltip";
import { useI18n } from "../../src/i18n";
import { shield } from "../../packages/excalidraw/components/icons";
import { Tooltip } from "../../packages/excalidraw/components/Tooltip";
import { useI18n } from "../../packages/excalidraw/i18n";
export const EncryptedIcon = () => {
const { t } = useI18n();

View File

@@ -1,25 +1,36 @@
import React from "react";
import { Card } from "../../src/components/Card";
import { ToolButton } from "../../src/components/ToolButton";
import { serializeAsJSON } from "../../src/data/json";
import { Card } from "../../packages/excalidraw/components/Card";
import { ToolButton } from "../../packages/excalidraw/components/ToolButton";
import { serializeAsJSON } from "../../packages/excalidraw/data/json";
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
import { FileId, NonDeletedExcalidrawElement } from "../../src/element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../src/types";
import {
FileId,
NonDeletedExcalidrawElement,
} from "../../packages/excalidraw/element/types";
import {
AppState,
BinaryFileData,
BinaryFiles,
} from "../../packages/excalidraw/types";
import { nanoid } from "nanoid";
import { useI18n } from "../../src/i18n";
import { encryptData, generateEncryptionKey } from "../../src/data/encryption";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import { useI18n } from "../../packages/excalidraw/i18n";
import {
encryptData,
generateEncryptionKey,
} from "../../packages/excalidraw/data/encryption";
import { isInitializedImageElement } from "../../packages/excalidraw/element/typeChecks";
import { FILE_UPLOAD_MAX_BYTES } from "../app_constants";
import { encodeFilesForUpload } from "../data/FileManager";
import { MIME_TYPES } from "../../src/constants";
import { trackEvent } from "../../src/analytics";
import { getFrame } from "../../src/utils";
import { ExcalidrawLogo } from "../../src/components/ExcalidrawLogo";
import { MIME_TYPES } from "../../packages/excalidraw/constants";
import { trackEvent } from "../../packages/excalidraw/analytics";
import { getFrame } from "../../packages/excalidraw/utils";
import { ExcalidrawLogo } from "../../packages/excalidraw/components/ExcalidrawLogo";
export const exportToExcalidrawPlus = async (
elements: readonly NonDeletedExcalidrawElement[],
appState: Partial<AppState>,
files: BinaryFiles,
name: string,
) => {
const firebase = await loadFirebaseStorage();
@@ -43,7 +54,7 @@ export const exportToExcalidrawPlus = async (
.ref(`/migrations/scenes/${id}`)
.put(blob, {
customMetadata: {
data: JSON.stringify({ version: 2, name: appState.name }),
data: JSON.stringify({ version: 2, name }),
created: Date.now().toString(),
},
});
@@ -79,9 +90,10 @@ export const ExportToExcalidrawPlus: React.FC<{
elements: readonly NonDeletedExcalidrawElement[];
appState: Partial<AppState>;
files: BinaryFiles;
name: string;
onError: (error: Error) => void;
onSuccess: () => void;
}> = ({ elements, appState, files, onError, onSuccess }) => {
}> = ({ elements, appState, files, name, onError, onSuccess }) => {
const { t } = useI18n();
return (
<Card color="primary">
@@ -107,7 +119,7 @@ export const ExportToExcalidrawPlus: React.FC<{
onClick={async () => {
try {
trackEvent("export", "eplus", `ui (${getFrame()})`);
await exportToExcalidrawPlus(elements, appState, files);
await exportToExcalidrawPlus(elements, appState, files, name);
onSuccess();
} catch (error: any) {
console.error(error);

View File

@@ -1,7 +1,7 @@
import oc from "open-color";
import React from "react";
import { THEME } from "../../src/constants";
import { Theme } from "../../src/element/types";
import { THEME } from "../../packages/excalidraw/constants";
import { Theme } from "../../packages/excalidraw/element/types";
// https://github.com/tholman/github-corners
export const GitHubCorner = React.memo(

View File

@@ -1,8 +1,8 @@
import { useSetAtom } from "jotai";
import React from "react";
import { appLangCodeAtom } from "..";
import { useI18n } from "../../src/i18n";
import { languages } from "../../src/i18n";
import { appLangCodeAtom } from "../App";
import { useI18n } from "../../packages/excalidraw/i18n";
import { languages } from "../../packages/excalidraw/i18n";
export const LanguageList = ({ style }: { style?: React.CSSProperties }) => {
const { t, langCode } = useI18n();

View File

@@ -1,7 +1,7 @@
import React from "react";
import * as Sentry from "@sentry/browser";
import { t } from "../i18n";
import Trans from "./Trans";
import { t } from "../../packages/excalidraw/i18n";
import Trans from "../../packages/excalidraw/components/Trans";
interface TopErrorBoundaryState {
hasError: boolean;
@@ -67,6 +67,8 @@ export class TopErrorBoundary extends React.Component<
window.open(
`https://github.com/excalidraw/excalidraw/issues/new?body=${body}`,
"_blank",
"noopener noreferrer",
);
}

View File

@@ -1,19 +1,19 @@
import { compressData } from "../../src/data/encode";
import { newElementWith } from "../../src/element/mutateElement";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import { compressData } from "../../packages/excalidraw/data/encode";
import { newElementWith } from "../../packages/excalidraw/element/mutateElement";
import { isInitializedImageElement } from "../../packages/excalidraw/element/typeChecks";
import {
ExcalidrawElement,
ExcalidrawImageElement,
FileId,
InitializedExcalidrawImageElement,
} from "../../src/element/types";
import { t } from "../../src/i18n";
} from "../../packages/excalidraw/element/types";
import { t } from "../../packages/excalidraw/i18n";
import {
BinaryFileData,
BinaryFileMetadata,
ExcalidrawImperativeAPI,
BinaryFiles,
} from "../../src/types";
} from "../../packages/excalidraw/types";
export class FileManager {
/** files being fetched */

View File

@@ -10,12 +10,30 @@
* (localStorage, indexedDB).
*/
import { createStore, entries, del, getMany, set, setMany } from "idb-keyval";
import { clearAppStateForLocalStorage } from "../../src/appState";
import { clearElementsForLocalStorage } from "../../src/element";
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../src/types";
import { debounce } from "../../src/utils";
import {
createStore,
entries,
del,
getMany,
set,
setMany,
get,
} from "idb-keyval";
import { clearAppStateForLocalStorage } from "../../packages/excalidraw/appState";
import { LibraryPersistedData } from "../../packages/excalidraw/data/library";
import { ImportedDataState } from "../../packages/excalidraw/data/types";
import { clearElementsForLocalStorage } from "../../packages/excalidraw/element";
import {
ExcalidrawElement,
FileId,
} from "../../packages/excalidraw/element/types";
import {
AppState,
BinaryFileData,
BinaryFiles,
} from "../../packages/excalidraw/types";
import { MaybePromise } from "../../packages/excalidraw/utility-types";
import { debounce } from "../../packages/excalidraw/utils";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT, STORAGE_KEYS } from "../app_constants";
import { FileManager } from "./FileManager";
import { Locker } from "./Locker";
@@ -176,3 +194,52 @@ export class LocalData {
},
});
}
export class LibraryIndexedDBAdapter {
/** IndexedDB database and store name */
private static idb_name = STORAGE_KEYS.IDB_LIBRARY;
/** library data store key */
private static key = "libraryData";
private static store = createStore(
`${LibraryIndexedDBAdapter.idb_name}-db`,
`${LibraryIndexedDBAdapter.idb_name}-store`,
);
static async load() {
const IDBData = await get<LibraryPersistedData>(
LibraryIndexedDBAdapter.key,
LibraryIndexedDBAdapter.store,
);
return IDBData || null;
}
static save(data: LibraryPersistedData): MaybePromise<void> {
return set(
LibraryIndexedDBAdapter.key,
data,
LibraryIndexedDBAdapter.store,
);
}
}
/** LS Adapter used only for migrating LS library data
* to indexedDB */
export class LibraryLocalStorageMigrationAdapter {
static load() {
const LSData = localStorage.getItem(
STORAGE_KEYS.__LEGACY_LOCAL_STORAGE_LIBRARY,
);
if (LSData != null) {
const libraryItems: ImportedDataState["libraryItems"] =
JSON.parse(LSData);
if (libraryItems) {
return { libraryItems };
}
}
return null;
}
static clear() {
localStorage.removeItem(STORAGE_KEYS.__LEGACY_LOCAL_STORAGE_LIBRARY);
}
}

View File

@@ -1,20 +1,31 @@
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { getSceneVersion } from "../../src/element";
import {
ExcalidrawElement,
FileId,
OrderedExcalidrawElement,
} from "../../packages/excalidraw/element/types";
import { getSceneVersion } from "../../packages/excalidraw/element";
import Portal from "../collab/Portal";
import { restoreElements } from "../../src/data/restore";
import { restoreElements } from "../../packages/excalidraw/data/restore";
import {
AppState,
BinaryFileData,
BinaryFileMetadata,
DataURL,
} from "../../src/types";
} from "../../packages/excalidraw/types";
import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants";
import { decompressData } from "../../src/data/encode";
import { encryptData, decryptData } from "../../src/data/encryption";
import { MIME_TYPES } from "../../src/constants";
import { reconcileElements } from "../collab/reconciliation";
import { decompressData } from "../../packages/excalidraw/data/encode";
import {
encryptData,
decryptData,
} from "../../packages/excalidraw/data/encryption";
import { MIME_TYPES } from "../../packages/excalidraw/constants";
import { getSyncableElements, SyncableExcalidrawElement } from ".";
import { ResolutionType } from "../../src/utility-types";
import { ResolutionType } from "../../packages/excalidraw/utility-types";
import type { Socket } from "socket.io-client";
import {
RemoteExcalidrawElement,
reconcileElements,
} from "../../packages/excalidraw/data/reconcile";
// private
// -----------------------------------------------------------------------------
@@ -132,12 +143,12 @@ const decryptElements = async (
};
class FirebaseSceneVersionCache {
private static cache = new WeakMap<SocketIOClient.Socket, number>();
static get = (socket: SocketIOClient.Socket) => {
private static cache = new WeakMap<Socket, number>();
static get = (socket: Socket) => {
return FirebaseSceneVersionCache.cache.get(socket);
};
static set = (
socket: SocketIOClient.Socket,
socket: Socket,
elements: readonly SyncableExcalidrawElement[],
) => {
FirebaseSceneVersionCache.cache.set(socket, getSceneVersion(elements));
@@ -223,7 +234,7 @@ export const saveToFirebase = async (
!socket ||
isSavedToFirebase(portal, elements)
) {
return false;
return null;
}
const firebase = await loadFirestore();
@@ -231,56 +242,59 @@ export const saveToFirebase = async (
const docRef = firestore.collection("scenes").doc(roomId);
const savedData = await firestore.runTransaction(async (transaction) => {
const storedScene = await firestore.runTransaction(async (transaction) => {
const snapshot = await transaction.get(docRef);
if (!snapshot.exists) {
const sceneDocument = await createFirebaseSceneDocument(
const storedScene = await createFirebaseSceneDocument(
firebase,
elements,
roomKey,
);
transaction.set(docRef, sceneDocument);
transaction.set(docRef, storedScene);
return {
elements,
reconciledElements: null,
};
return storedScene;
}
const prevDocData = snapshot.data() as FirebaseStoredScene;
const prevElements = getSyncableElements(
await decryptElements(prevDocData, roomKey),
const prevStoredScene = snapshot.data() as FirebaseStoredScene;
const prevStoredElements = getSyncableElements(
restoreElements(await decryptElements(prevStoredScene, roomKey), null),
);
const reconciledElements = getSyncableElements(
reconcileElements(elements, prevElements, appState),
reconcileElements(
elements,
prevStoredElements as OrderedExcalidrawElement[] as RemoteExcalidrawElement[],
appState,
),
);
const sceneDocument = await createFirebaseSceneDocument(
const storedScene = await createFirebaseSceneDocument(
firebase,
reconciledElements,
roomKey,
);
transaction.update(docRef, sceneDocument);
return {
elements,
reconciledElements,
};
transaction.update(docRef, storedScene);
// Return the stored elements as the in memory `reconciledElements` could have mutated in the meantime
return storedScene;
});
FirebaseSceneVersionCache.set(socket, savedData.elements);
const storedElements = getSyncableElements(
restoreElements(await decryptElements(storedScene, roomKey), null),
);
return { reconciledElements: savedData.reconciledElements };
FirebaseSceneVersionCache.set(socket, storedElements);
return storedElements;
};
export const loadFromFirebase = async (
roomId: string,
roomKey: string,
socket: SocketIOClient.Socket | null,
): Promise<readonly ExcalidrawElement[] | null> => {
socket: Socket | null,
): Promise<readonly SyncableExcalidrawElement[] | null> => {
const firebase = await loadFirestore();
const db = firebase.firestore();
@@ -291,14 +305,14 @@ export const loadFromFirebase = async (
}
const storedScene = doc.data() as FirebaseStoredScene;
const elements = getSyncableElements(
await decryptElements(storedScene, roomKey),
restoreElements(await decryptElements(storedScene, roomKey), null),
);
if (socket) {
FirebaseSceneVersionCache.set(socket, elements);
}
return restoreElements(elements, null);
return elements;
};
export const loadFilesFromFirebase = async (

View File

@@ -1,37 +1,47 @@
import { compressData, decompressData } from "../../src/data/encode";
import {
compressData,
decompressData,
} from "../../packages/excalidraw/data/encode";
import {
decryptData,
generateEncryptionKey,
IV_LENGTH_BYTES,
} from "../../src/data/encryption";
import { serializeAsJSON } from "../../src/data/json";
import { restore } from "../../src/data/restore";
import { ImportedDataState } from "../../src/data/types";
import { isInvisiblySmallElement } from "../../src/element/sizeHelpers";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { t } from "../../src/i18n";
} from "../../packages/excalidraw/data/encryption";
import { serializeAsJSON } from "../../packages/excalidraw/data/json";
import { restore } from "../../packages/excalidraw/data/restore";
import { ImportedDataState } from "../../packages/excalidraw/data/types";
import { SceneBounds } from "../../packages/excalidraw/element/bounds";
import { isInvisiblySmallElement } from "../../packages/excalidraw/element/sizeHelpers";
import { isInitializedImageElement } from "../../packages/excalidraw/element/typeChecks";
import {
ExcalidrawElement,
FileId,
OrderedExcalidrawElement,
} from "../../packages/excalidraw/element/types";
import { t } from "../../packages/excalidraw/i18n";
import {
AppState,
BinaryFileData,
BinaryFiles,
SocketId,
UserIdleState,
} from "../../src/types";
import { bytesToHexString } from "../../src/utils";
} from "../../packages/excalidraw/types";
import { MakeBrand } from "../../packages/excalidraw/utility-types";
import { bytesToHexString } from "../../packages/excalidraw/utils";
import {
DELETED_ELEMENT_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,
ROOM_ID_BYTES,
WS_SUBTYPES,
} from "../app_constants";
import { encodeFilesForUpload } from "./FileManager";
import { saveFilesToFirebase } from "./firebase";
export type SyncableExcalidrawElement = ExcalidrawElement & {
_brand: "SyncableExcalidrawElement";
};
export type SyncableExcalidrawElement = OrderedExcalidrawElement &
MakeBrand<"SyncableExcalidrawElement">;
export const isSyncableElement = (
element: ExcalidrawElement,
element: OrderedExcalidrawElement,
): element is SyncableExcalidrawElement => {
if (element.isDeleted) {
if (element.updated > Date.now() - DELETED_ELEMENT_TIMEOUT) {
@@ -42,7 +52,9 @@ export const isSyncableElement = (
return !isInvisiblySmallElement(element);
};
export const getSyncableElements = (elements: readonly ExcalidrawElement[]) =>
export const getSyncableElements = (
elements: readonly OrderedExcalidrawElement[],
) =>
elements.filter((element) =>
isSyncableElement(element),
) as SyncableExcalidrawElement[];
@@ -56,67 +68,49 @@ const generateRoomId = async () => {
return bytesToHexString(buffer);
};
/**
* Right now the reason why we resolve connection params (url, polling...)
* from upstream is to allow changing the params immediately when needed without
* having to wait for clients to update the SW.
*
* If REACT_APP_WS_SERVER_URL env is set, we use that instead (useful for forks)
*/
export const getCollabServer = async (): Promise<{
url: string;
polling: boolean;
}> => {
if (import.meta.env.VITE_APP_WS_SERVER_URL) {
return {
url: import.meta.env.VITE_APP_WS_SERVER_URL,
polling: true,
};
}
try {
const resp = await fetch(
`${import.meta.env.VITE_APP_PORTAL_URL}/collab-server`,
);
return await resp.json();
} catch (error) {
console.error(error);
throw new Error(t("errors.cannotResolveCollabServer"));
}
};
export type EncryptedData = {
data: ArrayBuffer;
iv: Uint8Array;
};
export type SocketUpdateDataSource = {
INVALID_RESPONSE: {
type: WS_SUBTYPES.INVALID_RESPONSE;
};
SCENE_INIT: {
type: "SCENE_INIT";
type: WS_SUBTYPES.INIT;
payload: {
elements: readonly ExcalidrawElement[];
};
};
SCENE_UPDATE: {
type: "SCENE_UPDATE";
type: WS_SUBTYPES.UPDATE;
payload: {
elements: readonly ExcalidrawElement[];
};
};
MOUSE_LOCATION: {
type: "MOUSE_LOCATION";
type: WS_SUBTYPES.MOUSE_LOCATION;
payload: {
socketId: string;
socketId: SocketId;
pointer: { x: number; y: number; tool: "pointer" | "laser" };
button: "down" | "up";
selectedElementIds: AppState["selectedElementIds"];
username: string;
};
};
IDLE_STATUS: {
type: "IDLE_STATUS";
USER_VISIBLE_SCENE_BOUNDS: {
type: WS_SUBTYPES.USER_VISIBLE_SCENE_BOUNDS;
payload: {
socketId: string;
socketId: SocketId;
username: string;
sceneBounds: SceneBounds;
};
};
IDLE_STATUS: {
type: WS_SUBTYPES.IDLE_STATUS;
payload: {
socketId: SocketId;
userState: UserIdleState;
username: string;
};
@@ -124,10 +118,7 @@ export type SocketUpdateDataSource = {
};
export type SocketUpdateDataIncoming =
| SocketUpdateDataSource[keyof SocketUpdateDataSource]
| {
type: "INVALID_RESPONSE";
};
SocketUpdateDataSource[keyof SocketUpdateDataSource];
export type SocketUpdateData =
SocketUpdateDataSource[keyof SocketUpdateDataSource] & {

View File

@@ -1,12 +1,11 @@
import { ExcalidrawElement } from "../../src/element/types";
import { AppState } from "../../src/types";
import { ExcalidrawElement } from "../../packages/excalidraw/element/types";
import { AppState } from "../../packages/excalidraw/types";
import {
clearAppStateForLocalStorage,
getDefaultAppState,
} from "../../src/appState";
import { clearElementsForLocalStorage } from "../../src/element";
} from "../../packages/excalidraw/appState";
import { clearElementsForLocalStorage } from "../../packages/excalidraw/element";
import { STORAGE_KEYS } from "../app_constants";
import { ImportedDataState } from "../../src/data/types";
export const saveUsernameToLocalStorage = (username: string) => {
try {
@@ -88,28 +87,13 @@ export const getTotalStorageSize = () => {
try {
const appState = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_APP_STATE);
const collab = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_COLLAB);
const library = localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_LIBRARY);
const appStateSize = appState?.length || 0;
const collabSize = collab?.length || 0;
const librarySize = library?.length || 0;
return appStateSize + collabSize + librarySize + getElementsStorageSize();
return appStateSize + collabSize + getElementsStorageSize();
} catch (error: any) {
console.error(error);
return 0;
}
};
export const getLibraryItemsFromStorage = () => {
try {
const libraryItems: ImportedDataState["libraryItems"] = JSON.parse(
localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_LIBRARY) as string,
);
return libraryItems || [];
} catch (error) {
console.error(error);
return [];
}
};

3
excalidraw-app/global.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
interface Window {
__EXCALIDRAW_SHA__: string | undefined;
}

View File

@@ -64,12 +64,30 @@
<!-- to minimize white flash on load when user has dark mode enabled -->
<script>
try {
//
const theme = window.localStorage.getItem("excalidraw-theme");
if (theme === "dark") {
document.documentElement.classList.add("dark");
function setTheme(theme) {
if (theme === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
}
} catch {}
function getTheme() {
const theme = window.localStorage.getItem("excalidraw-theme");
if (theme && theme === "system") {
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
} else {
return theme || "light";
}
}
setTheme(getTheme());
} catch (e) {
console.error("Error setting dark mode", e);
}
</script>
<style>
html.dark {
@@ -78,7 +96,7 @@
}
</style>
<!------------------------------------------------------------------------->
<% if ("%PROD%" === "true") { %>
<% if (typeof PROD != 'undefined' && PROD == true) { %>
<script>
// Redirect Excalidraw+ users which have auto-redirect enabled.
//
@@ -121,8 +139,9 @@
crossorigin="anonymous"
/>
<link rel="stylesheet" href="/fonts.css" type="text/css" />
<% if ("%VITE_APP_DEV_DISABLE_LIVE_RELOAD%"==="true" ) { %>
<link rel="stylesheet" href="/fonts/fonts.css" type="text/css" />
<% if (typeof VITE_APP_DEV_DISABLE_LIVE_RELOAD != 'undefined' &&
VITE_APP_DEV_DISABLE_LIVE_RELOAD == true) { %>
<script>
{
const _WebSocket = window.WebSocket;
@@ -195,8 +214,7 @@
<h1 class="visually-hidden">Excalidraw</h1>
</header>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
<% if ("%VITE_APP_DEV_DISABLE_LIVE_RELOAD%" !== 'true') { %>
<script type="module" src="index.tsx"></script>
<!-- 100% privacy friendly analytics -->
<script>
// need to load this script dynamically bcs. of iframe embed tracking
@@ -229,6 +247,5 @@
}
</script>
<!-- end LEGACY GOOGLE ANALYTICS -->
<% } %>
</body>
</html>

View File

@@ -4,6 +4,13 @@
&.theme--dark {
--color-primary-contrast-offset: #726dff; // to offset Chubb illusion
}
.top-right-ui {
display: flex;
justify-content: center;
align-items: flex-start;
}
.footer-center {
justify-content: flex-end;
margin-top: auto;
@@ -31,7 +38,7 @@
background-color: #ecfdf5;
color: #064e3c;
}
&.ExcalidrawPlus {
&.highlighted {
color: var(--color-promo);
}
}

View File

@@ -1,811 +1,15 @@
import polyfill from "../src/polyfill";
import LanguageDetector from "i18next-browser-languagedetector";
import { useEffect, useRef, useState } from "react";
import { trackEvent } from "../src/analytics";
import { getDefaultAppState } from "../src/appState";
import { ErrorDialog } from "../src/components/ErrorDialog";
import { TopErrorBoundary } from "../src/components/TopErrorBoundary";
import {
APP_NAME,
EVENT,
THEME,
TITLE_TIMEOUT,
VERSION_TIMEOUT,
} from "../src/constants";
import { loadFromBlob } from "../src/data/blob";
import {
ExcalidrawElement,
FileId,
NonDeletedExcalidrawElement,
Theme,
} from "../src/element/types";
import { useCallbackRefState } from "../src/hooks/useCallbackRefState";
import { t } from "../src/i18n";
import {
Excalidraw,
defaultLang,
LiveCollaborationTrigger,
} from "../src/packages/excalidraw/index";
import {
AppState,
LibraryItems,
ExcalidrawImperativeAPI,
BinaryFiles,
ExcalidrawInitialDataState,
UIAppState,
} from "../src/types";
import {
debounce,
getVersion,
getFrame,
isTestEnv,
preventUnload,
ResolvablePromise,
resolvablePromise,
isRunningInIframe,
} from "../src/utils";
import {
FIREBASE_STORAGE_PREFIXES,
STORAGE_KEYS,
SYNC_BROWSER_TABS_TIMEOUT,
} from "./app_constants";
import Collab, {
CollabAPI,
collabAPIAtom,
collabDialogShownAtom,
isCollaboratingAtom,
isOfflineAtom,
} from "./collab/Collab";
import {
exportToBackend,
getCollaborationLinkData,
isCollaborationLink,
loadScene,
} from "./data";
import {
getLibraryItemsFromStorage,
importFromLocalStorage,
importUsernameFromLocalStorage,
} from "./data/localStorage";
import CustomStats from "./CustomStats";
import {
restore,
restoreAppState,
RestoredDataState,
} from "../src/data/restore";
import {
ExportToExcalidrawPlus,
exportToExcalidrawPlus,
} from "./components/ExportToExcalidrawPlus";
import { updateStaleImageStatuses } from "./data/FileManager";
import { newElementWith } from "../src/element/mutateElement";
import { isInitializedImageElement } from "../src/element/typeChecks";
import { loadFilesFromFirebase } from "./data/firebase";
import { LocalData } from "./data/LocalData";
import { isBrowserStorageStateNewer } from "./data/tabSync";
import clsx from "clsx";
import { reconcileElements } from "./collab/reconciliation";
import {
parseLibraryTokensFromUrl,
useHandleLibrary,
} from "../src/data/library";
import { AppMainMenu } from "./components/AppMainMenu";
import { AppWelcomeScreen } from "./components/AppWelcomeScreen";
import { AppFooter } from "./components/AppFooter";
import { atom, Provider, useAtom, useAtomValue } from "jotai";
import { useAtomWithInitialValue } from "../src/jotai";
import { appJotaiStore } from "./app-jotai";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import ExcalidrawApp from "./App";
import { registerSW } from "virtual:pwa-register";
import "./index.scss";
import { ResolutionType } from "../src/utility-types";
import { ShareableLinkDialog } from "../src/components/ShareableLinkDialog";
import { openConfirmModal } from "../src/components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "../src/components/OverwriteConfirm/OverwriteConfirm";
import Trans from "../src/components/Trans";
polyfill();
window.EXCALIDRAW_THROTTLE_RENDER = true;
let isSelfEmbedding = false;
if (window.self !== window.top) {
try {
const parentUrl = new URL(document.referrer);
const currentUrl = new URL(window.location.href);
if (parentUrl.origin === currentUrl.origin) {
isSelfEmbedding = true;
}
} catch (error) {
// ignore
}
}
const languageDetector = new LanguageDetector();
languageDetector.init({
languageUtils: {},
});
const shareableLinkConfirmDialog = {
title: t("overwriteConfirm.modal.shareableLink.title"),
description: (
<Trans
i18nKey="overwriteConfirm.modal.shareableLink.description"
bold={(text) => <strong>{text}</strong>}
br={() => <br />}
/>
),
actionLabel: t("overwriteConfirm.modal.shareableLink.button"),
color: "danger",
} as const;
const initializeScene = async (opts: {
collabAPI: CollabAPI | null;
excalidrawAPI: ExcalidrawImperativeAPI;
}): Promise<
{ scene: ExcalidrawInitialDataState | null } & (
| { isExternalScene: true; id: string; key: string }
| { isExternalScene: false; id?: null; key?: null }
)
> => {
const searchParams = new URLSearchParams(window.location.search);
const id = searchParams.get("id");
const jsonBackendMatch = window.location.hash.match(
/^#json=([a-zA-Z0-9_-]+),([a-zA-Z0-9_-]+)$/,
);
const externalUrlMatch = window.location.hash.match(/^#url=(.*)$/);
const localDataState = importFromLocalStorage();
let scene: RestoredDataState & {
scrollToContent?: boolean;
} = await loadScene(null, null, localDataState);
let roomLinkData = getCollaborationLinkData(window.location.href);
const isExternalScene = !!(id || jsonBackendMatch || roomLinkData);
if (isExternalScene) {
if (
// don't prompt if scene is empty
!scene.elements.length ||
// don't prompt for collab scenes because we don't override local storage
roomLinkData ||
// otherwise, prompt whether user wants to override current scene
(await openConfirmModal(shareableLinkConfirmDialog))
) {
if (jsonBackendMatch) {
scene = await loadScene(
jsonBackendMatch[1],
jsonBackendMatch[2],
localDataState,
);
}
scene.scrollToContent = true;
if (!roomLinkData) {
window.history.replaceState({}, APP_NAME, window.location.origin);
}
} else {
// https://github.com/excalidraw/excalidraw/issues/1919
if (document.hidden) {
return new Promise((resolve, reject) => {
window.addEventListener(
"focus",
() => initializeScene(opts).then(resolve).catch(reject),
{
once: true,
},
);
});
}
roomLinkData = null;
window.history.replaceState({}, APP_NAME, window.location.origin);
}
} else if (externalUrlMatch) {
window.history.replaceState({}, APP_NAME, window.location.origin);
const url = externalUrlMatch[1];
try {
const request = await fetch(window.decodeURIComponent(url));
const data = await loadFromBlob(await request.blob(), null, null);
if (
!scene.elements.length ||
(await openConfirmModal(shareableLinkConfirmDialog))
) {
return { scene: data, isExternalScene };
}
} catch (error: any) {
return {
scene: {
appState: {
errorMessage: t("alerts.invalidSceneUrl"),
},
},
isExternalScene,
};
}
}
if (roomLinkData && opts.collabAPI) {
const { excalidrawAPI } = opts;
const scene = await opts.collabAPI.startCollaboration(roomLinkData);
return {
// when collaborating, the state may have already been updated at this
// point (we may have received updates from other clients), so reconcile
// elements and appState with existing state
scene: {
...scene,
appState: {
...restoreAppState(
{
...scene?.appState,
theme: localDataState?.appState?.theme || scene?.appState?.theme,
},
excalidrawAPI.getAppState(),
),
// necessary if we're invoking from a hashchange handler which doesn't
// go through App.initializeScene() that resets this flag
isLoading: false,
},
elements: reconcileElements(
scene?.elements || [],
excalidrawAPI.getSceneElementsIncludingDeleted(),
excalidrawAPI.getAppState(),
),
},
isExternalScene: true,
id: roomLinkData.roomId,
key: roomLinkData.roomKey,
};
} else if (scene) {
return isExternalScene && jsonBackendMatch
? {
scene,
isExternalScene,
id: jsonBackendMatch[1],
key: jsonBackendMatch[2],
}
: { scene, isExternalScene: false };
}
return { scene: null, isExternalScene: false };
};
const detectedLangCode = languageDetector.detect() || defaultLang.code;
export const appLangCodeAtom = atom(
Array.isArray(detectedLangCode) ? detectedLangCode[0] : detectedLangCode,
import "../excalidraw-app/sentry";
window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA;
const rootElement = document.getElementById("root")!;
const root = createRoot(rootElement);
registerSW();
root.render(
<StrictMode>
<ExcalidrawApp />
</StrictMode>,
);
const ExcalidrawWrapper = () => {
const [errorMessage, setErrorMessage] = useState("");
const [langCode, setLangCode] = useAtom(appLangCodeAtom);
const isCollabDisabled = isRunningInIframe();
// initial state
// ---------------------------------------------------------------------------
const initialStatePromiseRef = useRef<{
promise: ResolvablePromise<ExcalidrawInitialDataState | null>;
}>({ promise: null! });
if (!initialStatePromiseRef.current.promise) {
initialStatePromiseRef.current.promise =
resolvablePromise<ExcalidrawInitialDataState | null>();
}
useEffect(() => {
trackEvent("load", "frame", getFrame());
// Delayed so that the app has a time to load the latest SW
setTimeout(() => {
trackEvent("load", "version", getVersion());
}, VERSION_TIMEOUT);
}, []);
const [excalidrawAPI, excalidrawRefCallback] =
useCallbackRefState<ExcalidrawImperativeAPI>();
const [collabAPI] = useAtom(collabAPIAtom);
const [, setCollabDialogShown] = useAtom(collabDialogShownAtom);
const [isCollaborating] = useAtomWithInitialValue(isCollaboratingAtom, () => {
return isCollaborationLink(window.location.href);
});
useHandleLibrary({
excalidrawAPI,
getInitialLibraryItems: getLibraryItemsFromStorage,
});
useEffect(() => {
if (!excalidrawAPI || (!isCollabDisabled && !collabAPI)) {
return;
}
const loadImages = (
data: ResolutionType<typeof initializeScene>,
isInitialLoad = false,
) => {
if (!data.scene) {
return;
}
if (collabAPI?.isCollaborating()) {
if (data.scene.elements) {
collabAPI
.fetchImageFilesFromFirebase({
elements: data.scene.elements,
forceFetchFiles: true,
})
.then(({ loadedFiles, erroredFiles }) => {
excalidrawAPI.addFiles(loadedFiles);
updateStaleImageStatuses({
excalidrawAPI,
erroredFiles,
elements: excalidrawAPI.getSceneElementsIncludingDeleted(),
});
});
}
} else {
const fileIds =
data.scene.elements?.reduce((acc, element) => {
if (isInitializedImageElement(element)) {
return acc.concat(element.fileId);
}
return acc;
}, [] as FileId[]) || [];
if (data.isExternalScene) {
loadFilesFromFirebase(
`${FIREBASE_STORAGE_PREFIXES.shareLinkFiles}/${data.id}`,
data.key,
fileIds,
).then(({ loadedFiles, erroredFiles }) => {
excalidrawAPI.addFiles(loadedFiles);
updateStaleImageStatuses({
excalidrawAPI,
erroredFiles,
elements: excalidrawAPI.getSceneElementsIncludingDeleted(),
});
});
} else if (isInitialLoad) {
if (fileIds.length) {
LocalData.fileStorage
.getFiles(fileIds)
.then(({ loadedFiles, erroredFiles }) => {
if (loadedFiles.length) {
excalidrawAPI.addFiles(loadedFiles);
}
updateStaleImageStatuses({
excalidrawAPI,
erroredFiles,
elements: excalidrawAPI.getSceneElementsIncludingDeleted(),
});
});
}
// on fresh load, clear unused files from IDB (from previous
// session)
LocalData.fileStorage.clearObsoleteFiles({ currentFileIds: fileIds });
}
}
};
initializeScene({ collabAPI, excalidrawAPI }).then(async (data) => {
loadImages(data, /* isInitialLoad */ true);
initialStatePromiseRef.current.promise.resolve(data.scene);
});
const onHashChange = async (event: HashChangeEvent) => {
event.preventDefault();
const libraryUrlTokens = parseLibraryTokensFromUrl();
if (!libraryUrlTokens) {
if (
collabAPI?.isCollaborating() &&
!isCollaborationLink(window.location.href)
) {
collabAPI.stopCollaboration(false);
}
excalidrawAPI.updateScene({ appState: { isLoading: true } });
initializeScene({ collabAPI, excalidrawAPI }).then((data) => {
loadImages(data);
if (data.scene) {
excalidrawAPI.updateScene({
...data.scene,
...restore(data.scene, null, null, { repairBindings: true }),
commitToHistory: true,
});
}
});
}
};
const titleTimeout = setTimeout(
() => (document.title = APP_NAME),
TITLE_TIMEOUT,
);
const syncData = debounce(() => {
if (isTestEnv()) {
return;
}
if (
!document.hidden &&
((collabAPI && !collabAPI.isCollaborating()) || isCollabDisabled)
) {
// don't sync if local state is newer or identical to browser state
if (isBrowserStorageStateNewer(STORAGE_KEYS.VERSION_DATA_STATE)) {
const localDataState = importFromLocalStorage();
const username = importUsernameFromLocalStorage();
let langCode = languageDetector.detect() || defaultLang.code;
if (Array.isArray(langCode)) {
langCode = langCode[0];
}
setLangCode(langCode);
excalidrawAPI.updateScene({
...localDataState,
});
excalidrawAPI.updateLibrary({
libraryItems: getLibraryItemsFromStorage(),
});
collabAPI?.setUsername(username || "");
}
if (isBrowserStorageStateNewer(STORAGE_KEYS.VERSION_FILES)) {
const elements = excalidrawAPI.getSceneElementsIncludingDeleted();
const currFiles = excalidrawAPI.getFiles();
const fileIds =
elements?.reduce((acc, element) => {
if (
isInitializedImageElement(element) &&
// only load and update images that aren't already loaded
!currFiles[element.fileId]
) {
return acc.concat(element.fileId);
}
return acc;
}, [] as FileId[]) || [];
if (fileIds.length) {
LocalData.fileStorage
.getFiles(fileIds)
.then(({ loadedFiles, erroredFiles }) => {
if (loadedFiles.length) {
excalidrawAPI.addFiles(loadedFiles);
}
updateStaleImageStatuses({
excalidrawAPI,
erroredFiles,
elements: excalidrawAPI.getSceneElementsIncludingDeleted(),
});
});
}
}
}
}, SYNC_BROWSER_TABS_TIMEOUT);
const onUnload = () => {
LocalData.flushSave();
};
const visibilityChange = (event: FocusEvent | Event) => {
if (event.type === EVENT.BLUR || document.hidden) {
LocalData.flushSave();
}
if (
event.type === EVENT.VISIBILITY_CHANGE ||
event.type === EVENT.FOCUS
) {
syncData();
}
};
window.addEventListener(EVENT.HASHCHANGE, onHashChange, false);
window.addEventListener(EVENT.UNLOAD, onUnload, false);
window.addEventListener(EVENT.BLUR, visibilityChange, false);
document.addEventListener(EVENT.VISIBILITY_CHANGE, visibilityChange, false);
window.addEventListener(EVENT.FOCUS, visibilityChange, false);
return () => {
window.removeEventListener(EVENT.HASHCHANGE, onHashChange, false);
window.removeEventListener(EVENT.UNLOAD, onUnload, false);
window.removeEventListener(EVENT.BLUR, visibilityChange, false);
window.removeEventListener(EVENT.FOCUS, visibilityChange, false);
document.removeEventListener(
EVENT.VISIBILITY_CHANGE,
visibilityChange,
false,
);
clearTimeout(titleTimeout);
};
}, [isCollabDisabled, collabAPI, excalidrawAPI, setLangCode]);
useEffect(() => {
const unloadHandler = (event: BeforeUnloadEvent) => {
LocalData.flushSave();
if (
excalidrawAPI &&
LocalData.fileStorage.shouldPreventUnload(
excalidrawAPI.getSceneElements(),
)
) {
preventUnload(event);
}
};
window.addEventListener(EVENT.BEFORE_UNLOAD, unloadHandler);
return () => {
window.removeEventListener(EVENT.BEFORE_UNLOAD, unloadHandler);
};
}, [excalidrawAPI]);
useEffect(() => {
languageDetector.cacheUserLanguage(langCode);
}, [langCode]);
const [theme, setTheme] = useState<Theme>(
() =>
(localStorage.getItem(
STORAGE_KEYS.LOCAL_STORAGE_THEME,
) as Theme | null) ||
// FIXME migration from old LS scheme. Can be removed later. #5660
importFromLocalStorage().appState?.theme ||
THEME.LIGHT,
);
useEffect(() => {
localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_THEME, theme);
// currently only used for body styling during init (see public/index.html),
// but may change in the future
document.documentElement.classList.toggle("dark", theme === THEME.DARK);
}, [theme]);
const onChange = (
elements: readonly ExcalidrawElement[],
appState: AppState,
files: BinaryFiles,
) => {
if (collabAPI?.isCollaborating()) {
collabAPI.syncElements(elements);
}
setTheme(appState.theme);
// this check is redundant, but since this is a hot path, it's best
// not to evaludate the nested expression every time
if (!LocalData.isSavePaused()) {
LocalData.save(elements, appState, files, () => {
if (excalidrawAPI) {
let didChange = false;
const elements = excalidrawAPI
.getSceneElementsIncludingDeleted()
.map((element) => {
if (
LocalData.fileStorage.shouldUpdateImageElementStatus(element)
) {
const newElement = newElementWith(element, { status: "saved" });
if (newElement !== element) {
didChange = true;
}
return newElement;
}
return element;
});
if (didChange) {
excalidrawAPI.updateScene({
elements,
});
}
}
});
}
};
const [latestShareableLink, setLatestShareableLink] = useState<string | null>(
null,
);
const onExportToBackend = async (
exportedElements: readonly NonDeletedExcalidrawElement[],
appState: Partial<AppState>,
files: BinaryFiles,
canvas: HTMLCanvasElement,
) => {
if (exportedElements.length === 0) {
throw new Error(t("alerts.cannotExportEmptyCanvas"));
}
if (canvas) {
try {
const { url, errorMessage } = await exportToBackend(
exportedElements,
{
...appState,
viewBackgroundColor: appState.exportBackground
? appState.viewBackgroundColor
: getDefaultAppState().viewBackgroundColor,
},
files,
);
if (errorMessage) {
throw new Error(errorMessage);
}
if (url) {
setLatestShareableLink(url);
}
} catch (error: any) {
if (error.name !== "AbortError") {
const { width, height } = canvas;
console.error(error, { width, height });
throw new Error(error.message);
}
}
}
};
const renderCustomStats = (
elements: readonly NonDeletedExcalidrawElement[],
appState: UIAppState,
) => {
return (
<CustomStats
setToast={(message) => excalidrawAPI!.setToast({ message })}
appState={appState}
elements={elements}
/>
);
};
const onLibraryChange = async (items: LibraryItems) => {
if (!items.length) {
localStorage.removeItem(STORAGE_KEYS.LOCAL_STORAGE_LIBRARY);
return;
}
const serializedItems = JSON.stringify(items);
localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_LIBRARY, serializedItems);
};
const isOffline = useAtomValue(isOfflineAtom);
// browsers generally prevent infinite self-embedding, there are
// cases where it still happens, and while we disallow self-embedding
// by not whitelisting our own origin, this serves as an additional guard
if (isSelfEmbedding) {
return (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
height: "100%",
}}
>
<h1>I'm not a pretzel!</h1>
</div>
);
}
return (
<div
style={{ height: "100%" }}
className={clsx("excalidraw-app", {
"is-collaborating": isCollaborating,
})}
>
<Excalidraw
excalidrawAPI={excalidrawRefCallback}
onChange={onChange}
initialData={initialStatePromiseRef.current.promise}
isCollaborating={isCollaborating}
onPointerUpdate={collabAPI?.onPointerUpdate}
UIOptions={{
canvasActions: {
toggleTheme: true,
export: {
onExportToBackend,
renderCustomUI: (elements, appState, files) => {
return (
<ExportToExcalidrawPlus
elements={elements}
appState={appState}
files={files}
onError={(error) => {
excalidrawAPI?.updateScene({
appState: {
errorMessage: error.message,
},
});
}}
onSuccess={() => {
excalidrawAPI?.updateScene({
appState: { openDialog: null },
});
}}
/>
);
},
},
},
}}
langCode={langCode}
renderCustomStats={renderCustomStats}
detectScroll={false}
handleKeyboardGlobally={true}
onLibraryChange={onLibraryChange}
autoFocus={true}
theme={theme}
renderTopRightUI={(isMobile) => {
if (isMobile || !collabAPI || isCollabDisabled) {
return null;
}
return (
<LiveCollaborationTrigger
isCollaborating={isCollaborating}
onSelect={() => setCollabDialogShown(true)}
/>
);
}}
>
<AppMainMenu
setCollabDialogShown={setCollabDialogShown}
isCollaborating={isCollaborating}
isCollabEnabled={!isCollabDisabled}
/>
<AppWelcomeScreen
setCollabDialogShown={setCollabDialogShown}
isCollabEnabled={!isCollabDisabled}
/>
<OverwriteConfirmDialog>
<OverwriteConfirmDialog.Actions.ExportToImage />
<OverwriteConfirmDialog.Actions.SaveToDisk />
{excalidrawAPI && (
<OverwriteConfirmDialog.Action
title={t("overwriteConfirm.action.excalidrawPlus.title")}
actionLabel={t("overwriteConfirm.action.excalidrawPlus.button")}
onClick={() => {
exportToExcalidrawPlus(
excalidrawAPI.getSceneElements(),
excalidrawAPI.getAppState(),
excalidrawAPI.getFiles(),
);
}}
>
{t("overwriteConfirm.action.excalidrawPlus.description")}
</OverwriteConfirmDialog.Action>
)}
</OverwriteConfirmDialog>
<AppFooter />
{isCollaborating && isOffline && (
<div className="collab-offline-warning">
{t("alerts.collabOfflineWarning")}
</div>
)}
{latestShareableLink && (
<ShareableLinkDialog
link={latestShareableLink}
onCloseRequest={() => setLatestShareableLink(null)}
setErrorMessage={setErrorMessage}
/>
)}
{excalidrawAPI && !isCollabDisabled && (
<Collab excalidrawAPI={excalidrawAPI} />
)}
{errorMessage && (
<ErrorDialog onClose={() => setErrorMessage("")}>
{errorMessage}
</ErrorDialog>
)}
</Excalidraw>
</div>
);
};
const ExcalidrawApp = () => {
return (
<TopErrorBoundary>
<Provider unstable_createStore={() => appJotaiStore}>
<ExcalidrawWrapper />
</Provider>
</TopErrorBoundary>
);
};
export default ExcalidrawApp;

View File

@@ -0,0 +1,42 @@
{
"name": "excalidraw-app",
"version": "1.0.0",
"private": true,
"homepage": ".",
"browserslist": {
"production": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all",
"not safari < 12",
"not kaios <= 2.5",
"not edge < 79",
"not chrome < 70",
"not and_uc < 13",
"not samsung < 10"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=18.0.0"
},
"dependencies": {
"vite-plugin-html": "3.2.2"
},
"prettier": "@excalidraw/prettier-config",
"scripts": {
"build-node": "node ./scripts/build-node.js",
"build:app:docker": "cross-env VITE_APP_DISABLE_SENTRY=true VITE_APP_DISABLE_TRACKING=true vite build",
"build:app": "cross-env VITE_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA vite build",
"build:version": "node ../scripts/build-version.js",
"build": "yarn build:app && yarn build:version",
"start": "yarn && vite",
"start:production": "npm run build && npx http-server build -a localhost -p 5001 -o",
"build:preview": "yarn build && vite preview --port 5000"
}
}

Some files were not shown because too many files have changed in this diff Show More