@tldraw/editor 3.14.0-canary.f8af44c4d1e2 → 3.14.0-canary.fd17def565a1

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.
Files changed (122) hide show
  1. package/dist-cjs/index.d.ts +11 -21
  2. package/dist-cjs/index.js +8 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +41 -67
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
  7. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  8. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
  9. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  10. package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
  11. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
  12. package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
  13. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
  14. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
  15. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
  16. package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
  17. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
  18. package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
  19. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
  20. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
  21. package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
  22. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
  23. package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
  24. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
  25. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  26. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  27. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  28. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  29. package/dist-cjs/lib/utils/richText.js.map +1 -1
  30. package/dist-cjs/version.js +3 -3
  31. package/dist-cjs/version.js.map +1 -1
  32. package/dist-esm/index.d.mts +11 -21
  33. package/dist-esm/index.mjs +12 -8
  34. package/dist-esm/index.mjs.map +2 -2
  35. package/dist-esm/lib/editor/Editor.mjs +41 -67
  36. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  37. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  38. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  39. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  40. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  41. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  42. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  43. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  44. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  45. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  46. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  47. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
  48. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  49. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  50. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  51. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  52. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  53. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  54. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  55. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  56. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  57. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  58. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  59. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  60. package/dist-esm/lib/utils/richText.mjs.map +1 -1
  61. package/dist-esm/version.mjs +3 -3
  62. package/dist-esm/version.mjs.map +1 -1
  63. package/package.json +7 -7
  64. package/src/index.ts +13 -7
  65. package/src/lib/editor/Editor.test.ts +252 -3
  66. package/src/lib/editor/Editor.ts +43 -69
  67. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  68. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  69. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  70. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  71. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  72. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  73. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  74. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  75. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  76. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +1 -1
  77. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  78. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
  79. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  80. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  81. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  82. package/src/lib/editor/managers/TextManager/TextManager.test.ts +411 -0
  83. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +1 -1
  84. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  85. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  86. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  87. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  88. package/src/lib/editor/shapes/ShapeUtil.ts +1 -1
  89. package/src/lib/exports/getSvgJsx.tsx +1 -1
  90. package/src/lib/utils/reorderShapes.ts +10 -13
  91. package/src/lib/utils/richText.ts +1 -1
  92. package/src/version.ts +3 -3
  93. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  94. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  95. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  96. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  97. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  98. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  99. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  100. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  101. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  102. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  103. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  104. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  105. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  106. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  107. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  108. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  109. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  110. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  111. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  112. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  113. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  114. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  115. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  116. package/src/lib/editor/managers/Stack.ts +0 -71
  117. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  118. /package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +0 -0
  119. /package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +0 -0
  120. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +0 -0
  121. /package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +0 -0
  122. /package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +0 -0
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/lib/editor/managers/Stack.ts"],
4
- "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\n\nexport type Stack<T> = StackItem<T> | EmptyStackItem<T>\n\nexport function stack<T>(items?: Array<T>): Stack<T> {\n\tif (items) {\n\t\tlet result = EMPTY_STACK_ITEM as Stack<T>\n\t\twhile (items.length) {\n\t\t\tresult = result.push(items.pop()!)\n\t\t}\n\t\treturn result\n\t}\n\treturn EMPTY_STACK_ITEM as any\n}\n\nclass EmptyStackItem<T> implements Iterable<T> {\n\treadonly length = 0\n\treadonly head = null\n\treadonly tail: Stack<T> = this\n\n\tpush(head: T): Stack<T> {\n\t\treturn new StackItem<T>(head, this)\n\t}\n\n\ttoArray() {\n\t\treturn EMPTY_ARRAY\n\t}\n\n\t[Symbol.iterator]() {\n\t\treturn {\n\t\t\tnext() {\n\t\t\t\treturn { value: undefined, done: true as const }\n\t\t\t},\n\t\t}\n\t}\n}\n\nconst EMPTY_STACK_ITEM = new EmptyStackItem()\n\nclass StackItem<T> implements Iterable<T> {\n\tlength: number\n\tconstructor(\n\t\tpublic readonly head: T,\n\t\tpublic readonly tail: Stack<T>\n\t) {\n\t\tthis.length = tail.length + 1\n\t}\n\n\tpush(head: T): Stack<T> {\n\t\treturn new StackItem(head, this)\n\t}\n\n\ttoArray() {\n\t\treturn Array.from(this)\n\t}\n\n\t[Symbol.iterator]() {\n\t\tlet stack = this as Stack<T>\n\t\treturn {\n\t\t\tnext() {\n\t\t\t\tif (stack.length) {\n\t\t\t\t\tconst value = stack.head!\n\t\t\t\t\tstack = stack.tail\n\t\t\t\t\treturn { value, done: false as const }\n\t\t\t\t} else {\n\t\t\t\t\treturn { value: undefined, done: true as const }\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n"],
5
- "mappings": "AAAA,SAAS,mBAAmB;AAIrB,SAAS,MAAS,OAA4B;AACpD,MAAI,OAAO;AACV,QAAI,SAAS;AACb,WAAO,MAAM,QAAQ;AACpB,eAAS,OAAO,KAAK,MAAM,IAAI,CAAE;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAEA,MAAM,eAAyC;AAAA,EACrC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAiB;AAAA,EAE1B,KAAK,MAAmB;AACvB,WAAO,IAAI,UAAa,MAAM,IAAI;AAAA,EACnC;AAAA,EAEA,UAAU;AACT,WAAO;AAAA,EACR;AAAA,EAEA,CAAC,OAAO,QAAQ,IAAI;AACnB,WAAO;AAAA,MACN,OAAO;AACN,eAAO,EAAE,OAAO,QAAW,MAAM,KAAc;AAAA,MAChD;AAAA,IACD;AAAA,EACD;AACD;AAEA,MAAM,mBAAmB,IAAI,eAAe;AAE5C,MAAM,UAAoC;AAAA,EAEzC,YACiB,MACA,MACf;AAFe;AACA;AAEhB,SAAK,SAAS,KAAK,SAAS;AAAA,EAC7B;AAAA,EANA;AAAA,EAQA,KAAK,MAAmB;AACvB,WAAO,IAAI,UAAU,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,UAAU;AACT,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AAAA,EAEA,CAAC,OAAO,QAAQ,IAAI;AACnB,QAAIA,SAAQ;AACZ,WAAO;AAAA,MACN,OAAO;AACN,YAAIA,OAAM,QAAQ;AACjB,gBAAM,QAAQA,OAAM;AACpB,UAAAA,SAAQA,OAAM;AACd,iBAAO,EAAE,OAAO,MAAM,MAAe;AAAA,QACtC,OAAO;AACN,iBAAO,EAAE,OAAO,QAAW,MAAM,KAAc;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;",
6
- "names": ["stack"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/lib/editor/managers/TextManager.ts"],
4
- "sourcesContent": ["import { BoxModel, TLDefaultHorizontalAlignStyle } from '@tldraw/tlschema'\nimport { Editor } from '../Editor'\n\nconst fixNewLines = /\\r?\\n|\\r/g\n\nfunction normalizeTextForDom(text: string) {\n\treturn text\n\t\t.replace(fixNewLines, '\\n')\n\t\t.split('\\n')\n\t\t.map((x) => x || ' ')\n\t\t.join('\\n')\n}\n\nconst textAlignmentsForLtr = {\n\tstart: 'left',\n\t'start-legacy': 'left',\n\tmiddle: 'center',\n\t'middle-legacy': 'center',\n\tend: 'right',\n\t'end-legacy': 'right',\n}\n\n/** @public */\nexport interface TLMeasureTextSpanOpts {\n\toverflow: 'wrap' | 'truncate-ellipsis' | 'truncate-clip'\n\twidth: number\n\theight: number\n\tpadding: number\n\tfontSize: number\n\tfontWeight: string\n\tfontFamily: string\n\tfontStyle: string\n\tlineHeight: number\n\ttextAlign: TLDefaultHorizontalAlignStyle\n\totherStyles?: Record<string, string>\n}\n\nconst spaceCharacterRegex = /\\s/\n\n/** @public */\nexport class TextManager {\n\tprivate baseElem: HTMLDivElement\n\n\tconstructor(public editor: Editor) {\n\t\tthis.baseElem = document.createElement('div')\n\t\tthis.baseElem.classList.add('tl-text')\n\t\tthis.baseElem.classList.add('tl-text-measure')\n\t\tthis.baseElem.tabIndex = -1\n\t}\n\n\tmeasureText(\n\t\ttextToMeasure: string,\n\t\topts: {\n\t\t\tfontStyle: string\n\t\t\tfontWeight: string\n\t\t\tfontFamily: string\n\t\t\tfontSize: number\n\t\t\tlineHeight: number\n\t\t\t/**\n\t\t\t * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth\n\t\t\t * is null, the text will be measured without wrapping, but explicit line breaks and\n\t\t\t * space are preserved.\n\t\t\t */\n\t\t\tmaxWidth: null | number\n\t\t\tminWidth?: null | number\n\t\t\tpadding: string\n\t\t\tdisableOverflowWrapBreaking?: boolean\n\t\t}\n\t): BoxModel & { scrollWidth: number } {\n\t\tconst div = document.createElement('div')\n\t\tdiv.textContent = normalizeTextForDom(textToMeasure)\n\t\treturn this.measureHtml(div.innerHTML, opts)\n\t}\n\n\tmeasureHtml(\n\t\thtml: string,\n\t\topts: {\n\t\t\tfontStyle: string\n\t\t\tfontWeight: string\n\t\t\tfontFamily: string\n\t\t\tfontSize: number\n\t\t\tlineHeight: number\n\t\t\t/**\n\t\t\t * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth\n\t\t\t * is null, the text will be measured without wrapping, but explicit line breaks and\n\t\t\t * space are preserved.\n\t\t\t */\n\t\t\tmaxWidth: null | number\n\t\t\tminWidth?: null | number\n\t\t\totherStyles?: Record<string, string>\n\t\t\tpadding: string\n\t\t\tdisableOverflowWrapBreaking?: boolean\n\t\t}\n\t): BoxModel & { scrollWidth: number } {\n\t\t// Duplicate our base element; we don't need to clone deep\n\t\tconst wrapperElm = this.baseElem.cloneNode() as HTMLDivElement\n\t\tthis.editor.getContainer().appendChild(wrapperElm)\n\t\twrapperElm.innerHTML = html\n\t\tthis.baseElem.insertAdjacentElement('afterend', wrapperElm)\n\n\t\twrapperElm.setAttribute('dir', 'auto')\n\t\t// N.B. This property, while discouraged (\"intended for Document Type Definition (DTD) designers\")\n\t\t// is necessary for ensuring correct mixed RTL/LTR behavior when exporting SVGs.\n\t\twrapperElm.style.setProperty('unicode-bidi', 'plaintext')\n\t\twrapperElm.style.setProperty('font-family', opts.fontFamily)\n\t\twrapperElm.style.setProperty('font-style', opts.fontStyle)\n\t\twrapperElm.style.setProperty('font-weight', opts.fontWeight)\n\t\twrapperElm.style.setProperty('font-size', opts.fontSize + 'px')\n\t\twrapperElm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')\n\t\twrapperElm.style.setProperty('max-width', opts.maxWidth === null ? null : opts.maxWidth + 'px')\n\t\twrapperElm.style.setProperty('min-width', opts.minWidth === null ? null : opts.minWidth + 'px')\n\t\twrapperElm.style.setProperty('padding', opts.padding)\n\t\twrapperElm.style.setProperty(\n\t\t\t'overflow-wrap',\n\t\t\topts.disableOverflowWrapBreaking ? 'normal' : 'break-word'\n\t\t)\n\t\tif (opts.otherStyles) {\n\t\t\tfor (const [key, value] of Object.entries(opts.otherStyles)) {\n\t\t\t\twrapperElm.style.setProperty(key, value)\n\t\t\t}\n\t\t}\n\n\t\tconst scrollWidth = wrapperElm.scrollWidth\n\t\tconst rect = wrapperElm.getBoundingClientRect()\n\t\twrapperElm.remove()\n\n\t\treturn {\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tw: rect.width,\n\t\t\th: rect.height,\n\t\t\tscrollWidth,\n\t\t}\n\t}\n\n\t/**\n\t * Given an html element, measure the position of each span of unbroken\n\t * word/white-space characters within any text nodes it contains.\n\t */\n\tmeasureElementTextNodeSpans(\n\t\telement: HTMLElement,\n\t\t{ shouldTruncateToFirstLine = false }: { shouldTruncateToFirstLine?: boolean } = {}\n\t): { spans: { box: BoxModel; text: string }[]; didTruncate: boolean } {\n\t\tconst spans = []\n\n\t\t// Measurements of individual spans are relative to the containing element\n\t\tconst elmBounds = element.getBoundingClientRect()\n\t\tconst offsetX = -elmBounds.left\n\t\tconst offsetY = -elmBounds.top\n\n\t\t// we measure by creating a range that spans each character in the elements text node\n\t\tconst range = new Range()\n\t\tconst textNode = element.childNodes[0]\n\t\tlet idx = 0\n\n\t\tlet currentSpan = null\n\t\tlet prevCharWasSpaceCharacter = null\n\t\tlet prevCharTop = 0\n\t\tlet prevCharLeftForRTLTest = 0\n\t\tlet didTruncate = false\n\t\tfor (const childNode of element.childNodes) {\n\t\t\tif (childNode.nodeType !== Node.TEXT_NODE) continue\n\n\t\t\tfor (const char of childNode.textContent ?? '') {\n\t\t\t\t// place the range around the characters we're interested in\n\t\t\t\trange.setStart(textNode, idx)\n\t\t\t\trange.setEnd(textNode, idx + char.length)\n\t\t\t\t// measure the range. some browsers return multiple rects for the\n\t\t\t\t// first char in a new line - one for the line break, and one for\n\t\t\t\t// the character itself. we're only interested in the character.\n\t\t\t\tconst rects = range.getClientRects()\n\t\t\t\tconst rect = rects[rects.length - 1]!\n\n\t\t\t\t// calculate the position of the character relative to the element\n\t\t\t\tconst top = rect.top + offsetY\n\t\t\t\tconst left = rect.left + offsetX\n\t\t\t\tconst right = rect.right + offsetX\n\t\t\t\tconst isRTL = left < prevCharLeftForRTLTest\n\n\t\t\t\tconst isSpaceCharacter = spaceCharacterRegex.test(char)\n\t\t\t\tif (\n\t\t\t\t\t// If we're at a word boundary...\n\t\t\t\t\tisSpaceCharacter !== prevCharWasSpaceCharacter ||\n\t\t\t\t\t// ...or we're on a different line...\n\t\t\t\t\ttop !== prevCharTop ||\n\t\t\t\t\t// ...or we're at the start of the text and haven't created a span yet...\n\t\t\t\t\t!currentSpan\n\t\t\t\t) {\n\t\t\t\t\t// ...then we're at a span boundary!\n\n\t\t\t\t\tif (currentSpan) {\n\t\t\t\t\t\t// if we're truncating to a single line & we just finished the first line, stop there\n\t\t\t\t\t\tif (shouldTruncateToFirstLine && top !== prevCharTop) {\n\t\t\t\t\t\t\tdidTruncate = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// otherwise add the span to the list ready to start a new one\n\t\t\t\t\t\tspans.push(currentSpan)\n\t\t\t\t\t}\n\n\t\t\t\t\t// start a new span\n\t\t\t\t\tcurrentSpan = {\n\t\t\t\t\t\tbox: { x: left, y: top, w: rect.width, h: rect.height },\n\t\t\t\t\t\ttext: char,\n\t\t\t\t\t}\n\t\t\t\t\tprevCharLeftForRTLTest = left\n\t\t\t\t} else {\n\t\t\t\t\t// Looks like we're in RTL mode, so we need to adjust the left position.\n\t\t\t\t\tif (isRTL) {\n\t\t\t\t\t\tcurrentSpan.box.x = left\n\t\t\t\t\t}\n\n\t\t\t\t\t// otherwise we just need to extend the current span with the next character\n\t\t\t\t\tcurrentSpan.box.w = isRTL ? currentSpan.box.w + rect.width : right - currentSpan.box.x\n\t\t\t\t\tcurrentSpan.text += char\n\t\t\t\t}\n\n\t\t\t\tif (char === '\\n') {\n\t\t\t\t\tprevCharLeftForRTLTest = 0\n\t\t\t\t}\n\n\t\t\t\tprevCharWasSpaceCharacter = isSpaceCharacter\n\t\t\t\tprevCharTop = top\n\t\t\t\tidx += char.length\n\t\t\t}\n\t\t}\n\n\t\t// Add the last span\n\t\tif (currentSpan) {\n\t\t\tspans.push(currentSpan)\n\t\t}\n\n\t\treturn { spans, didTruncate }\n\t}\n\n\t/**\n\t * Measure text into individual spans. Spans are created by rendering the\n\t * text, then dividing it up according to line breaks and word boundaries.\n\t *\n\t * It works by having the browser render the text, then measuring the\n\t * position of each character. You can use this to replicate the text-layout\n\t * algorithm of the current browser in e.g. an SVG export.\n\t */\n\tmeasureTextSpans(\n\t\ttextToMeasure: string,\n\t\topts: TLMeasureTextSpanOpts\n\t): { text: string; box: BoxModel }[] {\n\t\tif (textToMeasure === '') return []\n\n\t\tconst elm = this.baseElem.cloneNode() as HTMLDivElement\n\t\tthis.editor.getContainer().appendChild(elm)\n\n\t\tconst elementWidth = Math.ceil(opts.width - opts.padding * 2)\n\t\telm.setAttribute('dir', 'auto')\n\t\t// N.B. This property, while discouraged (\"intended for Document Type Definition (DTD) designers\")\n\t\t// is necessary for ensuring correct mixed RTL/LTR behavior when exporting SVGs.\n\t\telm.style.setProperty('unicode-bidi', 'plaintext')\n\t\telm.style.setProperty('width', `${elementWidth}px`)\n\t\telm.style.setProperty('height', 'min-content')\n\t\telm.style.setProperty('font-size', `${opts.fontSize}px`)\n\t\telm.style.setProperty('font-family', opts.fontFamily)\n\t\telm.style.setProperty('font-weight', opts.fontWeight)\n\t\telm.style.setProperty('line-height', `${opts.lineHeight * opts.fontSize}px`)\n\t\telm.style.setProperty('text-align', textAlignmentsForLtr[opts.textAlign])\n\t\telm.style.setProperty('font-style', opts.fontStyle)\n\t\tif (opts.otherStyles) {\n\t\t\tfor (const [key, value] of Object.entries(opts.otherStyles)) {\n\t\t\t\telm.style.setProperty(key, value)\n\t\t\t}\n\t\t}\n\n\t\tconst shouldTruncateToFirstLine =\n\t\t\topts.overflow === 'truncate-ellipsis' || opts.overflow === 'truncate-clip'\n\n\t\tif (shouldTruncateToFirstLine) {\n\t\t\telm.style.setProperty('overflow-wrap', 'anywhere')\n\t\t\telm.style.setProperty('word-break', 'break-all')\n\t\t}\n\n\t\tconst normalizedText = normalizeTextForDom(textToMeasure)\n\n\t\t// Render the text into the measurement element:\n\t\telm.textContent = normalizedText\n\n\t\t// actually measure the text:\n\t\tconst { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {\n\t\t\tshouldTruncateToFirstLine,\n\t\t})\n\n\t\tif (opts.overflow === 'truncate-ellipsis' && didTruncate) {\n\t\t\t// we need to measure the ellipsis to know how much space it takes up\n\t\t\telm.textContent = '\u2026'\n\t\t\tconst ellipsisWidth = Math.ceil(this.measureElementTextNodeSpans(elm).spans[0].box.w)\n\n\t\t\t// then, we need to subtract that space from the width we have and measure again:\n\t\t\telm.style.setProperty('width', `${elementWidth - ellipsisWidth}px`)\n\t\t\telm.textContent = normalizedText\n\t\t\tconst truncatedSpans = this.measureElementTextNodeSpans(elm, {\n\t\t\t\tshouldTruncateToFirstLine: true,\n\t\t\t}).spans\n\n\t\t\t// Finally, we add in our ellipsis at the end of the last span. We\n\t\t\t// have to do this after measuring, not before, because adding the\n\t\t\t// ellipsis changes how whitespace might be getting collapsed by the\n\t\t\t// browser.\n\t\t\tconst lastSpan = truncatedSpans[truncatedSpans.length - 1]!\n\t\t\ttruncatedSpans.push({\n\t\t\t\ttext: '\u2026',\n\t\t\t\tbox: {\n\t\t\t\t\tx: Math.min(lastSpan.box.x + lastSpan.box.w, opts.width - opts.padding - ellipsisWidth),\n\t\t\t\t\ty: lastSpan.box.y,\n\t\t\t\t\tw: ellipsisWidth,\n\t\t\t\t\th: lastSpan.box.h,\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn truncatedSpans\n\t\t}\n\n\t\telm.remove()\n\n\t\treturn spans\n\t}\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/lib/editor/managers/TickManager.ts"],
4
- "sourcesContent": ["import { throttleToNextFrame as _throttleToNextFrame, bind } from '@tldraw/utils'\nimport { Vec } from '../../primitives/Vec'\nimport { Editor } from '../Editor'\n\nconst throttleToNextFrame =\n\ttypeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\t\t? // At test time we should use actual raf and not throttle, because throttle was set up to evaluate immediately during tests, which causes stack overflow\n\t\t\t// for the tick manager since it sets up a raf loop.\n\t\t\tfunction mockThrottle(cb: any) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\tconst frame = requestAnimationFrame(cb)\n\t\t\t\treturn () => cancelAnimationFrame(frame)\n\t\t\t}\n\t\t: _throttleToNextFrame\n\nexport class TickManager {\n\tconstructor(public editor: Editor) {\n\t\tthis.editor.disposables.add(this.dispose)\n\t\tthis.start()\n\t}\n\n\tcancelRaf?: null | (() => void)\n\tisPaused = true\n\tnow = 0\n\n\tstart() {\n\t\tthis.isPaused = false\n\t\tthis.cancelRaf?.()\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t\tthis.now = Date.now()\n\t}\n\n\t@bind\n\ttick() {\n\t\tif (this.isPaused) {\n\t\t\treturn\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst elapsed = now - this.now\n\t\tthis.now = now\n\n\t\tthis.updatePointerVelocity(elapsed)\n\t\tthis.editor.emit('frame', elapsed)\n\t\tthis.editor.emit('tick', elapsed)\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t}\n\n\t// Clear the listener\n\t@bind\n\tdispose() {\n\t\tthis.isPaused = true\n\n\t\tthis.cancelRaf?.()\n\t}\n\n\tprivate prevPoint = new Vec()\n\n\tupdatePointerVelocity(elapsed: number) {\n\t\tconst {\n\t\t\tprevPoint,\n\t\t\teditor: {\n\t\t\t\tinputs: { currentScreenPoint, pointerVelocity },\n\t\t\t},\n\t\t} = this\n\n\t\tif (elapsed === 0) return\n\n\t\tconst delta = Vec.Sub(currentScreenPoint, prevPoint)\n\t\tthis.prevPoint = currentScreenPoint.clone()\n\n\t\tconst length = delta.len()\n\t\tconst direction = length ? delta.div(length) : new Vec(0, 0)\n\n\t\t// consider adjusting this with an easing rather than a linear interpolation\n\t\tconst next = pointerVelocity.clone().lrp(direction.mul(length / elapsed), 0.5)\n\n\t\t// if the velocity is very small, just set it to 0\n\t\tif (Math.abs(next.x) < 0.01) next.x = 0\n\t\tif (Math.abs(next.y) < 0.01) next.y = 0\n\n\t\tif (!pointerVelocity.equals(next)) {\n\t\t\tthis.editor.inputs.pointerVelocity = next\n\t\t}\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,uBAAuB,sBAAsB,YAAY;AAClE,SAAS,WAAW;AAGpB,MAAM,sBACL,OAAO,YAAY,eAAe,QAAQ,IAAI,aAAa;AAAA;AAAA;AAAA,EAGzD,SAAS,aAAa,IAAS;AAE9B,UAAM,QAAQ,sBAAsB,EAAE;AACtC,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACxC;AAAA,IACC;AAmBH,aAAC,OAiBD,gBAAC;AAlCK,MAAM,YAAY;AAAA,EACxB,YAAmB,QAAgB;AAAhB;AADb;AAMN;AACA,oCAAW;AACX,+BAAM;AAiCN,wBAAQ,aAAY,IAAI,IAAI;AAvC3B,SAAK,OAAO,YAAY,IAAI,KAAK,OAAO;AACxC,SAAK,MAAM;AAAA,EACZ;AAAA,EAMA,QAAQ;AACP,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAC9C,SAAK,MAAM,KAAK,IAAI;AAAA,EACrB;AAAA,EAGA,OAAO;AACN,QAAI,KAAK,UAAU;AAClB;AAAA,IACD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,MAAM,KAAK;AAC3B,SAAK,MAAM;AAEX,SAAK,sBAAsB,OAAO;AAClC,SAAK,OAAO,KAAK,SAAS,OAAO;AACjC,SAAK,OAAO,KAAK,QAAQ,OAAO;AAChC,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAAA,EAC/C;AAAA,EAIA,UAAU;AACT,SAAK,WAAW;AAEhB,SAAK,YAAY;AAAA,EAClB;AAAA,EAIA,sBAAsB,SAAiB;AACtC,UAAM;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,QACP,QAAQ,EAAE,oBAAoB,gBAAgB;AAAA,MAC/C;AAAA,IACD,IAAI;AAEJ,QAAI,YAAY,EAAG;AAEnB,UAAM,QAAQ,IAAI,IAAI,oBAAoB,SAAS;AACnD,SAAK,YAAY,mBAAmB,MAAM;AAE1C,UAAM,SAAS,MAAM,IAAI;AACzB,UAAM,YAAY,SAAS,MAAM,IAAI,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC;AAG3D,UAAM,OAAO,gBAAgB,MAAM,EAAE,IAAI,UAAU,IAAI,SAAS,OAAO,GAAG,GAAG;AAG7E,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAM,MAAK,IAAI;AACtC,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAM,MAAK,IAAI;AAEtC,QAAI,CAAC,gBAAgB,OAAO,IAAI,GAAG;AAClC,WAAK,OAAO,OAAO,kBAAkB;AAAA,IACtC;AAAA,EACD;AACD;AAtEO;AAkBN,oCADA,WAjBY;AAmCZ,uCADA,cAlCY;AAAN,2BAAM;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/lib/editor/managers/UserPreferencesManager.ts"],
4
- "sourcesContent": ["import { atom, computed } from '@tldraw/state'\nimport { TLUserPreferences, defaultUserPreferences } from '../../config/TLUserPreferences'\nimport { TLUser } from '../../config/createTLUser'\n\n/** @public */\nexport class UserPreferencesManager {\n\tsystemColorScheme = atom<'dark' | 'light'>('systemColorScheme', 'light')\n\tdisposables = new Set<() => void>()\n\tdispose() {\n\t\tthis.disposables.forEach((d) => d())\n\t}\n\tconstructor(\n\t\tprivate readonly user: TLUser,\n\t\tprivate readonly inferDarkMode: boolean\n\t) {\n\t\tif (typeof window === 'undefined' || !('matchMedia' in window)) return\n\n\t\tconst darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n\t\tif (darkModeMediaQuery?.matches) {\n\t\t\tthis.systemColorScheme.set('dark')\n\t\t}\n\t\tconst handleChange = (e: MediaQueryListEvent) => {\n\t\t\tif (e.matches) {\n\t\t\t\tthis.systemColorScheme.set('dark')\n\t\t\t} else {\n\t\t\t\tthis.systemColorScheme.set('light')\n\t\t\t}\n\t\t}\n\t\tdarkModeMediaQuery?.addEventListener('change', handleChange)\n\t\tthis.disposables.add(() => darkModeMediaQuery?.removeEventListener('change', handleChange))\n\t}\n\n\tupdateUserPreferences(userPreferences: Partial<TLUserPreferences>) {\n\t\tthis.user.setUserPreferences({\n\t\t\t...this.user.userPreferences.get(),\n\t\t\t...userPreferences,\n\t\t})\n\t}\n\t@computed getUserPreferences() {\n\t\treturn {\n\t\t\tid: this.getId(),\n\t\t\tname: this.getName(),\n\t\t\tlocale: this.getLocale(),\n\t\t\tcolor: this.getColor(),\n\t\t\tanimationSpeed: this.getAnimationSpeed(),\n\t\t\tisSnapMode: this.getIsSnapMode(),\n\t\t\tcolorScheme: this.user.userPreferences.get().colorScheme,\n\t\t\tisDarkMode: this.getIsDarkMode(),\n\t\t\tisWrapMode: this.getIsWrapMode(),\n\t\t\tisDynamicResizeMode: this.getIsDynamicResizeMode(),\n\t\t}\n\t}\n\n\t@computed getIsDarkMode() {\n\t\tswitch (this.user.userPreferences.get().colorScheme) {\n\t\t\tcase 'dark':\n\t\t\t\treturn true\n\t\t\tcase 'light':\n\t\t\t\treturn false\n\t\t\tcase 'system':\n\t\t\t\treturn this.systemColorScheme.get() === 'dark'\n\t\t\tdefault:\n\t\t\t\treturn this.inferDarkMode ? this.systemColorScheme.get() === 'dark' : false\n\t\t}\n\t}\n\n\t/**\n\t * The speed at which the user can scroll by dragging toward the edge of the screen.\n\t */\n\t@computed getEdgeScrollSpeed() {\n\t\treturn this.user.userPreferences.get().edgeScrollSpeed ?? defaultUserPreferences.edgeScrollSpeed\n\t}\n\n\t@computed getAnimationSpeed() {\n\t\treturn this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed\n\t}\n\n\t@computed getId() {\n\t\treturn this.user.userPreferences.get().id\n\t}\n\n\t@computed getName() {\n\t\treturn this.user.userPreferences.get().name?.trim() ?? defaultUserPreferences.name\n\t}\n\n\t@computed getLocale() {\n\t\treturn this.user.userPreferences.get().locale ?? defaultUserPreferences.locale\n\t}\n\n\t@computed getColor() {\n\t\treturn this.user.userPreferences.get().color ?? defaultUserPreferences.color\n\t}\n\n\t@computed getIsSnapMode() {\n\t\treturn this.user.userPreferences.get().isSnapMode ?? defaultUserPreferences.isSnapMode\n\t}\n\n\t@computed getIsWrapMode() {\n\t\treturn this.user.userPreferences.get().isWrapMode ?? defaultUserPreferences.isWrapMode\n\t}\n\n\t@computed getIsDynamicResizeMode() {\n\t\treturn (\n\t\t\tthis.user.userPreferences.get().isDynamicSizeMode ?? defaultUserPreferences.isDynamicSizeMode\n\t\t)\n\t}\n\n\t@computed getIsPasteAtCursorMode() {\n\t\treturn (\n\t\t\tthis.user.userPreferences.get().isPasteAtCursorMode ??\n\t\t\tdefaultUserPreferences.isPasteAtCursorMode\n\t\t)\n\t}\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,32 +0,0 @@
1
- import { TestEditor } from '../../test/TestEditor'
2
- import { ScribbleManager } from './ScribbleManager'
3
-
4
- describe('ScribbleManager', () => {
5
- let editor: TestEditor
6
- let scribbleManager: ScribbleManager
7
-
8
- beforeEach(() => {
9
- editor = new TestEditor()
10
- scribbleManager = new ScribbleManager(editor)
11
- })
12
-
13
- it('add a point with a default z value', () => {
14
- const { id } = scribbleManager.addScribble({})
15
- scribbleManager.addPoint(id, 5, 10)
16
- scribbleManager.tick(0)
17
-
18
- expect(scribbleManager.scribbleItems.get(id)!.scribble.points).toEqual([
19
- { x: 5, y: 10, z: 0.5 },
20
- ])
21
- })
22
-
23
- it('add a point with a custom z value', () => {
24
- const { id } = scribbleManager.addScribble({})
25
- scribbleManager.addPoint(id, 5, 10, 0.7)
26
- scribbleManager.tick(0)
27
-
28
- expect(scribbleManager.scribbleItems.get(id)!.scribble.points).toEqual([
29
- { x: 5, y: 10, z: 0.7 },
30
- ])
31
- })
32
- })
@@ -1,71 +0,0 @@
1
- import { EMPTY_ARRAY } from '@tldraw/state'
2
-
3
- export type Stack<T> = StackItem<T> | EmptyStackItem<T>
4
-
5
- export function stack<T>(items?: Array<T>): Stack<T> {
6
- if (items) {
7
- let result = EMPTY_STACK_ITEM as Stack<T>
8
- while (items.length) {
9
- result = result.push(items.pop()!)
10
- }
11
- return result
12
- }
13
- return EMPTY_STACK_ITEM as any
14
- }
15
-
16
- class EmptyStackItem<T> implements Iterable<T> {
17
- readonly length = 0
18
- readonly head = null
19
- readonly tail: Stack<T> = this
20
-
21
- push(head: T): Stack<T> {
22
- return new StackItem<T>(head, this)
23
- }
24
-
25
- toArray() {
26
- return EMPTY_ARRAY
27
- }
28
-
29
- [Symbol.iterator]() {
30
- return {
31
- next() {
32
- return { value: undefined, done: true as const }
33
- },
34
- }
35
- }
36
- }
37
-
38
- const EMPTY_STACK_ITEM = new EmptyStackItem()
39
-
40
- class StackItem<T> implements Iterable<T> {
41
- length: number
42
- constructor(
43
- public readonly head: T,
44
- public readonly tail: Stack<T>
45
- ) {
46
- this.length = tail.length + 1
47
- }
48
-
49
- push(head: T): Stack<T> {
50
- return new StackItem(head, this)
51
- }
52
-
53
- toArray() {
54
- return Array.from(this)
55
- }
56
-
57
- [Symbol.iterator]() {
58
- let stack = this as Stack<T>
59
- return {
60
- next() {
61
- if (stack.length) {
62
- const value = stack.head!
63
- stack = stack.tail
64
- return { value, done: false as const }
65
- } else {
66
- return { value: undefined, done: true as const }
67
- }
68
- },
69
- }
70
- }
71
- }