@tldraw/editor 3.9.0-canary.ffd990988638 → 3.9.0-internal.7f0e15f4f7d9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +228 -3
- package/dist-cjs/index.js +9 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +33 -6
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +7 -0
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +63 -8
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager.js +167 -0
- package/dist-cjs/lib/editor/managers/FontManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/TextManager.js +23 -17
- package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +11 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/FontEmbedder.js +7 -2
- package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/exportToSvg.js +3 -2
- package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgAsImage.js +1 -1
- package/dist-cjs/lib/exports/getSvgAsImage.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js +18 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +1 -0
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +3 -1
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -1
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +48 -0
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +7 -0
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useViewportHeight.js +56 -0
- package/dist-cjs/lib/hooks/useViewportHeight.js.map +7 -0
- package/dist-cjs/lib/license/LicenseManager.js +1 -1
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/options.js +2 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js +104 -28
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +3 -3
- package/dist-cjs/lib/utils/dom.js +1 -1
- package/dist-cjs/lib/utils/dom.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js +46 -0
- package/dist-cjs/lib/utils/richText.js.map +7 -0
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +228 -3
- package/dist-esm/index.mjs +13 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +34 -7
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +8 -1
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +71 -9
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager.mjs +153 -0
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/TextManager.mjs +23 -17
- package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +11 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs +7 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/exportToSvg.mjs +3 -2
- package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgAsImage.mjs +1 -1
- package/dist-esm/lib/exports/getSvgAsImage.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +19 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +1 -0
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +3 -1
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +1 -1
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +28 -0
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +7 -0
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useViewportHeight.mjs +36 -0
- package/dist-esm/lib/hooks/useViewportHeight.mjs.map +7 -0
- package/dist-esm/lib/license/LicenseManager.mjs +1 -1
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +2 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +104 -18
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
- package/dist-esm/lib/utils/dom.mjs +1 -1
- package/dist-esm/lib/utils/dom.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs +26 -0
- package/dist-esm/lib/utils/richText.mjs.map +7 -0
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +127 -13
- package/package.json +10 -9
- package/src/index.ts +15 -0
- package/src/lib/TldrawEditor.tsx +52 -4
- package/src/lib/components/Shape.tsx +9 -1
- package/src/lib/editor/Editor.ts +91 -7
- package/src/lib/editor/managers/FontManager.ts +252 -0
- package/src/lib/editor/managers/TextManager.ts +42 -17
- package/src/lib/editor/shapes/ShapeUtil.ts +13 -0
- package/src/lib/editor/types/emit-types.ts +1 -0
- package/src/lib/editor/types/external-content.ts +1 -0
- package/src/lib/exports/FontEmbedder.ts +13 -1
- package/src/lib/exports/StyleEmbedder.ts +1 -1
- package/src/lib/exports/exportToSvg.tsx +4 -3
- package/src/lib/exports/getSvgAsImage.ts +1 -1
- package/src/lib/exports/getSvgJsx.tsx +22 -2
- package/src/lib/exports/parseCss.ts +1 -0
- package/src/lib/globals/environment.ts +3 -0
- package/src/lib/hooks/useCanvasEvents.ts +2 -1
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -0
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +29 -0
- package/src/lib/hooks/usePassThroughWheelEvents.ts +0 -1
- package/src/lib/hooks/useViewportHeight.ts +37 -0
- package/src/lib/license/LicenseManager.test.ts +16 -13
- package/src/lib/license/LicenseManager.ts +2 -2
- package/src/lib/options.ts +7 -0
- package/src/lib/utils/browserCanvasMaxSize.ts +121 -21
- package/src/lib/utils/dom.ts +1 -1
- package/src/lib/utils/richText.ts +72 -0
- package/src/version.ts +3 -3
package/editor.css
CHANGED
|
@@ -156,6 +156,8 @@
|
|
|
156
156
|
--color-text-1: hsl(0, 0%, 18%);
|
|
157
157
|
--color-text-3: hsl(220, 2%, 65%);
|
|
158
158
|
--color-text-shadow: hsl(0, 0%, 100%);
|
|
159
|
+
--color-text-highlight: hsl(52, 100%, 50%);
|
|
160
|
+
--color-text-highlight-p3: color(display-p3 0.972 0.8205 0.05);
|
|
159
161
|
--color-primary: hsl(214, 84%, 56%);
|
|
160
162
|
--color-success: hsl(123, 46%, 34%);
|
|
161
163
|
--color-info: hsl(201, 98%, 41%);
|
|
@@ -202,6 +204,8 @@
|
|
|
202
204
|
--color-text-1: hsl(0, 0%, 85%);
|
|
203
205
|
--color-text-3: hsl(210, 6%, 45%);
|
|
204
206
|
--color-text-shadow: hsl(210, 13%, 18%);
|
|
207
|
+
--color-text-highlight: hsl(52, 100%, 41%);
|
|
208
|
+
--color-text-highlight-p3: color(display-p3 0.8078 0.6225 0.0312);
|
|
205
209
|
--color-primary: hsl(214, 84%, 56%);
|
|
206
210
|
--color-success: hsl(123, 38%, 57%);
|
|
207
211
|
--color-info: hsl(199, 92%, 56%);
|
|
@@ -248,7 +252,7 @@
|
|
|
248
252
|
input,
|
|
249
253
|
*[contenteditable],
|
|
250
254
|
*[contenteditable] * {
|
|
251
|
-
|
|
255
|
+
user-select: text;
|
|
252
256
|
}
|
|
253
257
|
|
|
254
258
|
/* -------------------------------------------------- */
|
|
@@ -722,17 +726,14 @@ input,
|
|
|
722
726
|
opacity: 0.7;
|
|
723
727
|
}
|
|
724
728
|
|
|
725
|
-
/*
|
|
726
|
-
/* Spinner */
|
|
727
|
-
/* -------------------------------------------------- */
|
|
728
|
-
|
|
729
|
+
/* --------------------- Spinner -------------------- */
|
|
729
730
|
@keyframes spinner {
|
|
730
731
|
to {
|
|
731
732
|
transform: rotate(360deg);
|
|
732
733
|
}
|
|
733
734
|
}
|
|
734
735
|
|
|
735
|
-
/*
|
|
736
|
+
/* ---------------------- Text ---------------------- */
|
|
736
737
|
|
|
737
738
|
.tl-text-shape-label {
|
|
738
739
|
position: relative;
|
|
@@ -782,10 +783,14 @@ input,
|
|
|
782
783
|
text-align: right;
|
|
783
784
|
}
|
|
784
785
|
|
|
785
|
-
.tl-text-wrapper[data-isediting='true'] .tl-text-content {
|
|
786
|
+
.tl-plain-text-wrapper[data-isediting='true'] .tl-text-content {
|
|
786
787
|
opacity: 0;
|
|
787
788
|
}
|
|
788
789
|
|
|
790
|
+
.tl-rich-text-wrapper[data-isediting='true'] .tl-text-content {
|
|
791
|
+
display: none;
|
|
792
|
+
}
|
|
793
|
+
|
|
789
794
|
.tl-text {
|
|
790
795
|
/* remove overflow from textarea on windows */
|
|
791
796
|
margin: 0px;
|
|
@@ -852,7 +857,6 @@ input,
|
|
|
852
857
|
width: 100%;
|
|
853
858
|
min-width: 1px;
|
|
854
859
|
min-height: 1px;
|
|
855
|
-
overflow: visible;
|
|
856
860
|
outline: none;
|
|
857
861
|
}
|
|
858
862
|
|
|
@@ -868,6 +872,7 @@ input,
|
|
|
868
872
|
}
|
|
869
873
|
|
|
870
874
|
.tl-text-content {
|
|
875
|
+
overflow: visible;
|
|
871
876
|
pointer-events: none;
|
|
872
877
|
}
|
|
873
878
|
|
|
@@ -875,10 +880,17 @@ input,
|
|
|
875
880
|
resize: none;
|
|
876
881
|
user-select: all;
|
|
877
882
|
-webkit-user-select: text;
|
|
878
|
-
overflow: hidden;
|
|
879
883
|
cursor: var(--tl-cursor-text);
|
|
880
884
|
}
|
|
881
885
|
|
|
886
|
+
.tl-text-input:not(.tl-rich-text) {
|
|
887
|
+
/*
|
|
888
|
+
* Note: this `overflow: hidden` is key for scrollbars to not show up
|
|
889
|
+
* plaintext/<textarea> editors.
|
|
890
|
+
*/
|
|
891
|
+
overflow: hidden;
|
|
892
|
+
}
|
|
893
|
+
|
|
882
894
|
.tl-text-wrapper[data-isediting='false'] .tl-text-input,
|
|
883
895
|
.tl-arrow-label[data-isediting='false'] .tl-text-input {
|
|
884
896
|
opacity: 0;
|
|
@@ -891,6 +903,109 @@ input,
|
|
|
891
903
|
text-shadow: none;
|
|
892
904
|
}
|
|
893
905
|
|
|
906
|
+
.tl-rich-text[data-iseditinganything='true'] {
|
|
907
|
+
cursor: var(--tl-cursor-text);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
.tl-rich-text .ProseMirror {
|
|
911
|
+
word-wrap: break-word;
|
|
912
|
+
overflow-wrap: break-word;
|
|
913
|
+
white-space: pre-wrap;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Note: ProseMirror disables this in https://github.com/ProseMirror/prosemirror-view/commit/6b3b2205e2f3029cb8e8e86c55a190a22491df31
|
|
917
|
+
* However, that was from 8 years ago and the browser caret issue
|
|
918
|
+
* it mentions seems to be fixed. So, we're re-enabling it.
|
|
919
|
+
* We'll tell ProseMirror maybe to get rid of this on their end.
|
|
920
|
+
*/
|
|
921
|
+
-webkit-font-variant-ligatures: inherit;
|
|
922
|
+
font-variant-ligatures: inherit;
|
|
923
|
+
font-feature-settings: inherit;
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* N.B. This following CSS Rule comes standard with the tiptap editor.
|
|
927
|
+
* Combined with the above rule that it supersedes, it allows for
|
|
928
|
+
* the auto-linking to work in text. Say, when typing example.com
|
|
929
|
+
* this helps it automatically turn that bit of text into a link.
|
|
930
|
+
*
|
|
931
|
+
* However, specifically, the break-spaces features seems to cause
|
|
932
|
+
* rendering differences when going in-and-out of edit mode. For example,
|
|
933
|
+
* the statically rendered text 'the rain in spain falls mainly on the plain'
|
|
934
|
+
* in a note shape will render differently when going in-and-out of edit mode.
|
|
935
|
+
*
|
|
936
|
+
* So, this is commented out to help make both the autolinking work (which now
|
|
937
|
+
* relies on the white-space: pre-wrap to work and to make the static/edit-mode
|
|
938
|
+
* rendering consistent.
|
|
939
|
+
* In the future, we might consider just making the static rendering just use
|
|
940
|
+
* white-space: break-spaces to make it consistent with the edit mode if need be.
|
|
941
|
+
*
|
|
942
|
+
* Also, the amount of ink I've spilt in my career writing comments explaining
|
|
943
|
+
* white-space in contenteditable is incredible.
|
|
944
|
+
*
|
|
945
|
+
/* white-space: break-spaces; */
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.tl-rich-text p {
|
|
949
|
+
margin: 0;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.tl-rich-text ul,
|
|
953
|
+
.tl-rich-text ol {
|
|
954
|
+
text-align: left;
|
|
955
|
+
margin: 0;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.tl-rich-text h1,
|
|
959
|
+
.tl-rich-text h2,
|
|
960
|
+
.tl-rich-text h3,
|
|
961
|
+
.tl-rich-text h4,
|
|
962
|
+
.tl-rich-text h5,
|
|
963
|
+
.tl-rich-text h6 {
|
|
964
|
+
margin-top: 5px;
|
|
965
|
+
margin-bottom: 10px;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.tl-rich-text a {
|
|
969
|
+
color: var(--color-primary);
|
|
970
|
+
text-decoration: underline;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
.tl-rich-text code {
|
|
974
|
+
font-family: var(--tl-font-mono);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
.tl-rich-text mark {
|
|
978
|
+
background-color: #fddd00;
|
|
979
|
+
color: currentColor;
|
|
980
|
+
border-radius: 2px;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.tl-theme__light .tl-rich-text mark {
|
|
984
|
+
text-shadow: none;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.tl-theme__dark .tl-rich-text mark {
|
|
988
|
+
background-color: var(--color-text-highlight);
|
|
989
|
+
color: currentColor;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
@supports (color: color(display-p3 1 1 1)) {
|
|
993
|
+
@media (color-gamut: p3) {
|
|
994
|
+
.tl-container:not(.tl-theme__force-sRGB) .tl-rich-text mark {
|
|
995
|
+
background-color: var(--color-text-highlight-p3);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.tl-text-label__inner > .tl-text-input.tl-rich-text {
|
|
1001
|
+
display: none;
|
|
1002
|
+
position: static;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.tl-text-wrapper[data-isediting='true'] .tl-rich-text {
|
|
1006
|
+
display: block;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
894
1009
|
/* ------------------- Snap Lines ------------------- */
|
|
895
1010
|
|
|
896
1011
|
.tl-snap-indicator {
|
|
@@ -1175,10 +1290,6 @@ input,
|
|
|
1175
1290
|
min-height: auto;
|
|
1176
1291
|
}
|
|
1177
1292
|
|
|
1178
|
-
.tl-text-label[data-isediting='true'] p {
|
|
1179
|
-
opacity: 0;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
1293
|
.tl-arrow-hint {
|
|
1183
1294
|
stroke: var(--color-text-1);
|
|
1184
1295
|
fill: none;
|
|
@@ -1270,6 +1381,9 @@ input,
|
|
|
1270
1381
|
opacity: 0;
|
|
1271
1382
|
animation: fade-in 0.2s ease-in-out forwards;
|
|
1272
1383
|
animation-delay: 0.2s;
|
|
1384
|
+
position: absolute;
|
|
1385
|
+
inset: 0px;
|
|
1386
|
+
z-index: var(--layer-canvas-blocker);
|
|
1273
1387
|
}
|
|
1274
1388
|
|
|
1275
1389
|
@keyframes fade-in {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "A tiny little drawing app (editor).",
|
|
4
|
-
"version": "3.9.0-
|
|
4
|
+
"version": "3.9.0-internal.7f0e15f4f7d9",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -45,15 +45,17 @@
|
|
|
45
45
|
"lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"@tldraw/
|
|
52
|
-
"@tldraw/
|
|
53
|
-
"@tldraw/
|
|
48
|
+
"@tiptap/core": "^2.9.1",
|
|
49
|
+
"@tiptap/pm": "^2.9.1",
|
|
50
|
+
"@tiptap/react": "^2.9.1",
|
|
51
|
+
"@tldraw/state": "3.9.0-internal.7f0e15f4f7d9",
|
|
52
|
+
"@tldraw/state-react": "3.9.0-internal.7f0e15f4f7d9",
|
|
53
|
+
"@tldraw/store": "3.9.0-internal.7f0e15f4f7d9",
|
|
54
|
+
"@tldraw/tlschema": "3.9.0-internal.7f0e15f4f7d9",
|
|
55
|
+
"@tldraw/utils": "3.9.0-internal.7f0e15f4f7d9",
|
|
56
|
+
"@tldraw/validate": "3.9.0-internal.7f0e15f4f7d9",
|
|
54
57
|
"@types/core-js": "^2.5.8",
|
|
55
58
|
"@use-gesture/react": "^10.3.1",
|
|
56
|
-
"canvas-size": "~2.0.0",
|
|
57
59
|
"classnames": "^2.5.1",
|
|
58
60
|
"core-js": "^3.40.0",
|
|
59
61
|
"eventemitter3": "^4.0.7",
|
|
@@ -70,7 +72,6 @@
|
|
|
70
72
|
"@testing-library/jest-dom": "^5.17.0",
|
|
71
73
|
"@testing-library/react": "^15.0.7",
|
|
72
74
|
"@types/benchmark": "^2.1.5",
|
|
73
|
-
"@types/canvas-size": "^1.2.2",
|
|
74
75
|
"@types/wicg-file-system-access": "^2020.9.8",
|
|
75
76
|
"benchmark": "^2.1.4",
|
|
76
77
|
"fake-indexeddb": "^4.0.2",
|
package/src/index.ts
CHANGED
|
@@ -26,6 +26,14 @@ export {
|
|
|
26
26
|
useValue,
|
|
27
27
|
} from '@tldraw/state-react'
|
|
28
28
|
export { resizeScaled } from './lib/editor/shapes/shared/resizeScaled'
|
|
29
|
+
export {
|
|
30
|
+
getFontsFromRichText,
|
|
31
|
+
type RichTextFontVisitor,
|
|
32
|
+
type RichTextFontVisitorState,
|
|
33
|
+
type TLTextOptions,
|
|
34
|
+
type TiptapEditor,
|
|
35
|
+
type TiptapNode,
|
|
36
|
+
} from './lib/utils/richText'
|
|
29
37
|
export { LocalIndexedDb, Table, type StoreName } from './lib/utils/sync/LocalIndexedDb'
|
|
30
38
|
// eslint-disable-next-line local/no-export-star
|
|
31
39
|
export * from '@tldraw/store'
|
|
@@ -163,6 +171,11 @@ export {
|
|
|
163
171
|
} from './lib/editor/bindings/BindingUtil'
|
|
164
172
|
export { ClickManager, type TLClickState } from './lib/editor/managers/ClickManager'
|
|
165
173
|
export { EdgeScrollManager } from './lib/editor/managers/EdgeScrollManager'
|
|
174
|
+
export {
|
|
175
|
+
FontManager,
|
|
176
|
+
type TLFontFace,
|
|
177
|
+
type TLFontFaceSource,
|
|
178
|
+
} from './lib/editor/managers/FontManager'
|
|
166
179
|
export { HistoryManager } from './lib/editor/managers/HistoryManager'
|
|
167
180
|
export { ScribbleManager, type ScribbleItem } from './lib/editor/managers/ScribbleManager'
|
|
168
181
|
export {
|
|
@@ -297,6 +310,7 @@ export { useIsCropping } from './lib/hooks/useIsCropping'
|
|
|
297
310
|
export { useIsDarkMode } from './lib/hooks/useIsDarkMode'
|
|
298
311
|
export { useIsEditing } from './lib/hooks/useIsEditing'
|
|
299
312
|
export { useLocalStore } from './lib/hooks/useLocalStore'
|
|
313
|
+
export { usePassThroughMouseOverEvents } from './lib/hooks/usePassThroughMouseOverEvents'
|
|
300
314
|
export { usePassThroughWheelEvents } from './lib/hooks/usePassThroughWheelEvents'
|
|
301
315
|
export { usePeerIds } from './lib/hooks/usePeerIds'
|
|
302
316
|
export { usePresence } from './lib/hooks/usePresence'
|
|
@@ -311,6 +325,7 @@ export {
|
|
|
311
325
|
export { useSelectionEvents } from './lib/hooks/useSelectionEvents'
|
|
312
326
|
export { useTLSchemaFromUtils, useTLStore } from './lib/hooks/useTLStore'
|
|
313
327
|
export { useTransform } from './lib/hooks/useTransform'
|
|
328
|
+
export { useViewportHeight } from './lib/hooks/useViewportHeight'
|
|
314
329
|
export {
|
|
315
330
|
LicenseManager,
|
|
316
331
|
type InvalidLicenseKeyResult,
|
package/src/lib/TldrawEditor.tsx
CHANGED
|
@@ -14,7 +14,6 @@ import React, {
|
|
|
14
14
|
} from 'react'
|
|
15
15
|
|
|
16
16
|
import classNames from 'classnames'
|
|
17
|
-
import { TLDeepLinkOptions } from '..'
|
|
18
17
|
import { version } from '../version'
|
|
19
18
|
import { OptionalErrorBoundary } from './components/ErrorBoundary'
|
|
20
19
|
import { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback'
|
|
@@ -44,7 +43,9 @@ import { useZoomCss } from './hooks/useZoomCss'
|
|
|
44
43
|
import { LicenseProvider } from './license/LicenseProvider'
|
|
45
44
|
import { Watermark } from './license/Watermark'
|
|
46
45
|
import { TldrawOptions } from './options'
|
|
46
|
+
import { TLDeepLinkOptions } from './utils/deepLinks'
|
|
47
47
|
import { stopEventPropagation } from './utils/dom'
|
|
48
|
+
import { TLTextOptions } from './utils/richText'
|
|
48
49
|
import { TLStoreWithStatus } from './utils/sync/StoreWithStatus'
|
|
49
50
|
|
|
50
51
|
/**
|
|
@@ -167,6 +168,11 @@ export interface TldrawEditorBaseProps {
|
|
|
167
168
|
*/
|
|
168
169
|
cameraOptions?: Partial<TLCameraOptions>
|
|
169
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Text options for the editor.
|
|
173
|
+
*/
|
|
174
|
+
textOptions?: TLTextOptions
|
|
175
|
+
|
|
170
176
|
/**
|
|
171
177
|
* Options for the editor.
|
|
172
178
|
*/
|
|
@@ -190,6 +196,11 @@ export interface TldrawEditorBaseProps {
|
|
|
190
196
|
* remain in the store and participate in all other operations.
|
|
191
197
|
*/
|
|
192
198
|
isShapeHidden?(shape: TLShape, editor: Editor): boolean
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The URLs for the fonts to use in the editor.
|
|
202
|
+
*/
|
|
203
|
+
assetUrls?: { fonts?: { [key: string]: string | undefined } }
|
|
193
204
|
}
|
|
194
205
|
|
|
195
206
|
/**
|
|
@@ -372,10 +383,12 @@ function TldrawEditorWithReadyStore({
|
|
|
372
383
|
autoFocus = true,
|
|
373
384
|
inferDarkMode,
|
|
374
385
|
cameraOptions,
|
|
386
|
+
textOptions,
|
|
375
387
|
options,
|
|
376
388
|
licenseKey,
|
|
377
389
|
deepLinks: _deepLinks,
|
|
378
390
|
isShapeHidden,
|
|
391
|
+
assetUrls,
|
|
379
392
|
}: Required<
|
|
380
393
|
TldrawEditorProps & {
|
|
381
394
|
store: TLStore
|
|
@@ -430,9 +443,11 @@ function TldrawEditorWithReadyStore({
|
|
|
430
443
|
autoFocus,
|
|
431
444
|
inferDarkMode,
|
|
432
445
|
cameraOptions,
|
|
446
|
+
textOptions,
|
|
433
447
|
options,
|
|
434
448
|
licenseKey,
|
|
435
449
|
isShapeHidden,
|
|
450
|
+
fontAssetUrls: assetUrls?.fonts,
|
|
436
451
|
})
|
|
437
452
|
|
|
438
453
|
editor.updateViewportScreenBounds(canvasRef.current ?? container)
|
|
@@ -467,6 +482,8 @@ function TldrawEditorWithReadyStore({
|
|
|
467
482
|
setEditor,
|
|
468
483
|
licenseKey,
|
|
469
484
|
isShapeHidden,
|
|
485
|
+
textOptions,
|
|
486
|
+
assetUrls,
|
|
470
487
|
]
|
|
471
488
|
)
|
|
472
489
|
|
|
@@ -532,10 +549,41 @@ function TldrawEditorWithReadyStore({
|
|
|
532
549
|
[editor, autoFocus]
|
|
533
550
|
)
|
|
534
551
|
|
|
535
|
-
const
|
|
552
|
+
const [_fontLoadingState, setFontLoadingState] = useState<{
|
|
553
|
+
editor: Editor
|
|
554
|
+
isLoaded: boolean
|
|
555
|
+
} | null>(null)
|
|
556
|
+
let fontLoadingState = _fontLoadingState
|
|
557
|
+
if (editor !== fontLoadingState?.editor) {
|
|
558
|
+
const newFontLoadingState = editor ? { editor, isLoaded: false } : null
|
|
559
|
+
if (fontLoadingState !== newFontLoadingState) setFontLoadingState(newFontLoadingState)
|
|
560
|
+
fontLoadingState = newFontLoadingState
|
|
561
|
+
}
|
|
562
|
+
useEffect(() => {
|
|
563
|
+
if (!editor) return
|
|
564
|
+
let isCancelled = false
|
|
536
565
|
|
|
537
|
-
|
|
538
|
-
|
|
566
|
+
editor.fonts
|
|
567
|
+
.loadRequiredFontsForCurrentPage(editor.options.maxFontsToLoadBeforeRender)
|
|
568
|
+
.finally(() => {
|
|
569
|
+
if (isCancelled) return
|
|
570
|
+
setFontLoadingState({ editor, isLoaded: true })
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
return () => {
|
|
574
|
+
isCancelled = true
|
|
575
|
+
}
|
|
576
|
+
}, [editor])
|
|
577
|
+
|
|
578
|
+
const { Canvas, LoadingScreen } = useEditorComponents()
|
|
579
|
+
|
|
580
|
+
if (!editor || !fontLoadingState?.isLoaded) {
|
|
581
|
+
return (
|
|
582
|
+
<>
|
|
583
|
+
{LoadingScreen && <LoadingScreen />}
|
|
584
|
+
<div className="tl-canvas" ref={canvasRef} />
|
|
585
|
+
</>
|
|
586
|
+
)
|
|
539
587
|
}
|
|
540
588
|
|
|
541
589
|
return (
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { react } from '@tldraw/state'
|
|
1
2
|
import { useQuickReactor, useStateTracking } from '@tldraw/state-react'
|
|
2
3
|
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
3
|
-
import { memo, useCallback, useRef } from 'react'
|
|
4
|
+
import { memo, useCallback, useEffect, useRef } from 'react'
|
|
4
5
|
import { ShapeUtil } from '../editor/shapes/ShapeUtil'
|
|
5
6
|
import { useEditor } from '../hooks/useEditor'
|
|
6
7
|
import { useEditorComponents } from '../hooks/useEditorComponents'
|
|
@@ -41,6 +42,13 @@ export const Shape = memo(function Shape({
|
|
|
41
42
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
42
43
|
const bgContainerRef = useRef<HTMLDivElement>(null)
|
|
43
44
|
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
return react('load fonts', () => {
|
|
47
|
+
const fonts = editor.fonts.getShapeFontFaces(shape)
|
|
48
|
+
editor.fonts.requestFonts(fonts)
|
|
49
|
+
})
|
|
50
|
+
}, [editor, shape])
|
|
51
|
+
|
|
44
52
|
const memoizedStuffRef = useRef({
|
|
45
53
|
transform: '',
|
|
46
54
|
clipPath: 'none',
|
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Atom,
|
|
3
|
+
EMPTY_ARRAY,
|
|
4
|
+
atom,
|
|
5
|
+
computed,
|
|
6
|
+
react,
|
|
7
|
+
transact,
|
|
8
|
+
unsafe__withoutCapture,
|
|
9
|
+
} from '@tldraw/state'
|
|
2
10
|
import {
|
|
3
11
|
ComputedCache,
|
|
4
12
|
RecordType,
|
|
@@ -34,6 +42,7 @@ import {
|
|
|
34
42
|
TLImageAsset,
|
|
35
43
|
TLInstance,
|
|
36
44
|
TLInstancePageState,
|
|
45
|
+
TLNoteShape,
|
|
37
46
|
TLPOINTER_ID,
|
|
38
47
|
TLPage,
|
|
39
48
|
TLPageId,
|
|
@@ -129,6 +138,7 @@ import {
|
|
|
129
138
|
import { getIncrementedName } from '../utils/getIncrementedName'
|
|
130
139
|
import { isAccelKey } from '../utils/keyboard'
|
|
131
140
|
import { getReorderingShapesChanges } from '../utils/reorderShapes'
|
|
141
|
+
import { TLTextOptions, TiptapEditor } from '../utils/richText'
|
|
132
142
|
import { applyRotationToSnapshotShapes, getRotationSnapshot } from '../utils/rotation'
|
|
133
143
|
import { BindingOnDeleteOptions, BindingUtil } from './bindings/BindingUtil'
|
|
134
144
|
import { bindingsIndex } from './derivations/bindingsIndex'
|
|
@@ -138,6 +148,7 @@ import { deriveShapeIdsInCurrentPage } from './derivations/shapeIdsInCurrentPage
|
|
|
138
148
|
import { ClickManager } from './managers/ClickManager'
|
|
139
149
|
import { EdgeScrollManager } from './managers/EdgeScrollManager'
|
|
140
150
|
import { FocusManager } from './managers/FocusManager'
|
|
151
|
+
import { FontManager } from './managers/FontManager'
|
|
141
152
|
import { HistoryManager } from './managers/HistoryManager'
|
|
142
153
|
import { ScribbleManager } from './managers/ScribbleManager'
|
|
143
154
|
import { SnapManager } from './managers/SnapManager/SnapManager'
|
|
@@ -224,8 +235,10 @@ export interface TLEditorOptions {
|
|
|
224
235
|
* Options for the editor's camera.
|
|
225
236
|
*/
|
|
226
237
|
cameraOptions?: Partial<TLCameraOptions>
|
|
238
|
+
textOptions?: TLTextOptions
|
|
227
239
|
options?: Partial<TldrawOptions>
|
|
228
240
|
licenseKey?: string
|
|
241
|
+
fontAssetUrls?: { [key: string]: string | undefined }
|
|
229
242
|
/**
|
|
230
243
|
* A predicate that should return true if the given shape should be hidden.
|
|
231
244
|
* @param shape - The shape to check.
|
|
@@ -262,11 +275,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
262
275
|
tools,
|
|
263
276
|
getContainer,
|
|
264
277
|
cameraOptions,
|
|
278
|
+
textOptions,
|
|
265
279
|
initialState,
|
|
266
280
|
autoFocus,
|
|
267
281
|
inferDarkMode,
|
|
268
282
|
options,
|
|
269
283
|
isShapeHidden,
|
|
284
|
+
fontAssetUrls,
|
|
270
285
|
}: TLEditorOptions) {
|
|
271
286
|
super()
|
|
272
287
|
|
|
@@ -290,12 +305,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
290
305
|
|
|
291
306
|
this._cameraOptions.set({ ...DEFAULT_CAMERA_OPTIONS, ...cameraOptions })
|
|
292
307
|
|
|
308
|
+
this._textOptions = atom('text options', textOptions ?? null)
|
|
309
|
+
|
|
293
310
|
this.user = new UserPreferencesManager(user ?? createTLUser(), inferDarkMode ?? false)
|
|
294
311
|
this.disposables.add(() => this.user.dispose())
|
|
295
312
|
|
|
296
313
|
this.getContainer = getContainer
|
|
297
314
|
|
|
298
315
|
this.textMeasure = new TextManager(this)
|
|
316
|
+
this.fonts = new FontManager(this, fontAssetUrls)
|
|
317
|
+
|
|
299
318
|
this._tickManager = new TickManager(this)
|
|
300
319
|
|
|
301
320
|
class NewRoot extends RootState {
|
|
@@ -834,6 +853,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
834
853
|
*/
|
|
835
854
|
readonly textMeasure: TextManager
|
|
836
855
|
|
|
856
|
+
/**
|
|
857
|
+
* A utility for managing the set of fonts that should be rendered in the document.
|
|
858
|
+
*
|
|
859
|
+
* @public
|
|
860
|
+
*/
|
|
861
|
+
readonly fonts: FontManager
|
|
862
|
+
|
|
837
863
|
/**
|
|
838
864
|
* A manager for the editor's environment.
|
|
839
865
|
*
|
|
@@ -2022,6 +2048,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2022
2048
|
*/
|
|
2023
2049
|
setEditingShape(shape: TLShapeId | TLShape | null): this {
|
|
2024
2050
|
const id = typeof shape === 'string' ? shape : (shape?.id ?? null)
|
|
2051
|
+
this.setRichTextEditor(null)
|
|
2025
2052
|
if (id !== this.getEditingShapeId()) {
|
|
2026
2053
|
if (id) {
|
|
2027
2054
|
const shape = this.getShape(id)
|
|
@@ -2040,6 +2067,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2040
2067
|
this.run(
|
|
2041
2068
|
() => {
|
|
2042
2069
|
this._updateCurrentPageState({ editingShapeId: null })
|
|
2070
|
+
this._currentRichTextEditor.set(null)
|
|
2043
2071
|
},
|
|
2044
2072
|
{ history: 'ignore' }
|
|
2045
2073
|
)
|
|
@@ -2047,6 +2075,42 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2047
2075
|
return this
|
|
2048
2076
|
}
|
|
2049
2077
|
|
|
2078
|
+
// Rich text editor
|
|
2079
|
+
|
|
2080
|
+
private _currentRichTextEditor = atom('rich text editor', null as TiptapEditor | null)
|
|
2081
|
+
|
|
2082
|
+
/**
|
|
2083
|
+
* The current editing shape's text editor.
|
|
2084
|
+
*
|
|
2085
|
+
* @public
|
|
2086
|
+
*/
|
|
2087
|
+
@computed getRichTextEditor(): TiptapEditor | null {
|
|
2088
|
+
return this._currentRichTextEditor.get()
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* Set the current editing shape's rich text editor.
|
|
2093
|
+
*
|
|
2094
|
+
* @example
|
|
2095
|
+
* ```ts
|
|
2096
|
+
* editor.setRichTextEditor(richTextEditorView)
|
|
2097
|
+
* ```
|
|
2098
|
+
*
|
|
2099
|
+
* @param textEditor - The text editor to set as the current editing shape's text editor.
|
|
2100
|
+
*
|
|
2101
|
+
* @public
|
|
2102
|
+
*/
|
|
2103
|
+
setRichTextEditor(textEditor: TiptapEditor | null) {
|
|
2104
|
+
// If the new editor is different from the current one, destroy the current one
|
|
2105
|
+
const current = this._currentRichTextEditor.__unsafe__getWithoutCapture()
|
|
2106
|
+
if (current !== textEditor) {
|
|
2107
|
+
current?.destroy()
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
this._currentRichTextEditor.set(textEditor)
|
|
2111
|
+
return this
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2050
2114
|
// Hovered
|
|
2051
2115
|
|
|
2052
2116
|
/**
|
|
@@ -2103,6 +2167,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2103
2167
|
@computed getHintingShapeIds() {
|
|
2104
2168
|
return this.getCurrentPageState().hintingShapeIds
|
|
2105
2169
|
}
|
|
2170
|
+
|
|
2106
2171
|
/**
|
|
2107
2172
|
* The editor's current hinting shapes.
|
|
2108
2173
|
*
|
|
@@ -2251,6 +2316,21 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2251
2316
|
return this
|
|
2252
2317
|
}
|
|
2253
2318
|
|
|
2319
|
+
private _textOptions: Atom<TLTextOptions | null>
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* Get the current text options.
|
|
2323
|
+
*
|
|
2324
|
+
* @example
|
|
2325
|
+
* ```ts
|
|
2326
|
+
* editor.getTextOptions()
|
|
2327
|
+
* ```
|
|
2328
|
+
*
|
|
2329
|
+
* @public */
|
|
2330
|
+
getTextOptions() {
|
|
2331
|
+
return assertExists(this._textOptions.get(), 'Cannot use text without setting textOptions')
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2254
2334
|
/* --------------------- Camera --------------------- */
|
|
2255
2335
|
|
|
2256
2336
|
/** @internal */
|
|
@@ -4207,8 +4287,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4207
4287
|
private _getShapeGeometryCache(): ComputedCache<Geometry2d, TLShape> {
|
|
4208
4288
|
return this.store.createComputedCache(
|
|
4209
4289
|
'bounds',
|
|
4210
|
-
(shape) =>
|
|
4211
|
-
|
|
4290
|
+
(shape) => {
|
|
4291
|
+
this.fonts.trackFontsForShape(shape)
|
|
4292
|
+
return this.getShapeUtil(shape).getGeometry(shape)
|
|
4293
|
+
},
|
|
4294
|
+
{ areRecordsEqual: (a, b) => a.props === b.props }
|
|
4212
4295
|
)
|
|
4213
4296
|
}
|
|
4214
4297
|
|
|
@@ -4758,9 +4841,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4758
4841
|
// Check labels first
|
|
4759
4842
|
if (
|
|
4760
4843
|
this.isShapeOfType<TLFrameShape>(shape, 'frame') ||
|
|
4761
|
-
(
|
|
4844
|
+
(this.isShapeOfType<TLArrowShape>(shape, 'arrow') && shape.props.text.trim()) ||
|
|
4845
|
+
((this.isShapeOfType<TLNoteShape>(shape, 'note') ||
|
|
4762
4846
|
(this.isShapeOfType<TLGeoShape>(shape, 'geo') && shape.props.fill === 'none')) &&
|
|
4763
|
-
shape.
|
|
4847
|
+
this.getShapeUtil(shape).getText(shape)?.trim())
|
|
4764
4848
|
) {
|
|
4765
4849
|
for (const childGeometry of (geometry as Group2d).children) {
|
|
4766
4850
|
if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
|
|
@@ -7007,7 +7091,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7007
7091
|
* @example
|
|
7008
7092
|
* ```ts
|
|
7009
7093
|
* editor.createShape(myShape)
|
|
7010
|
-
* editor.createShape({ id: 'box1', type: 'text', props: {
|
|
7094
|
+
* editor.createShape({ id: 'box1', type: 'text', props: { richText: toRichText("ok") } })
|
|
7011
7095
|
* ```
|
|
7012
7096
|
*
|
|
7013
7097
|
* @param shape - The shape (or shape partial) to create.
|
|
@@ -7025,7 +7109,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7025
7109
|
* @example
|
|
7026
7110
|
* ```ts
|
|
7027
7111
|
* editor.createShapes([myShape])
|
|
7028
|
-
* editor.createShapes([{ id: 'box1', type: 'text', props: {
|
|
7112
|
+
* editor.createShapes([{ id: 'box1', type: 'text', props: { richText: toRichText("ok") } }])
|
|
7029
7113
|
* ```
|
|
7030
7114
|
*
|
|
7031
7115
|
* @param shapes - The shapes (or shape partials) to create.
|