@tldraw/editor 3.16.0-canary.56eb315c11ae → 3.16.0-canary.6074088f67bd

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 (137) hide show
  1. package/dist-cjs/index.d.ts +129 -9
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +8 -2
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/Shape.js +7 -10
  9. package/dist-cjs/lib/components/Shape.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
  11. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
  14. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  17. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  19. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  20. package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
  21. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  22. package/dist-cjs/lib/editor/Editor.js +74 -34
  23. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +9 -4
  25. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  27. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  29. package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
  30. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  31. package/dist-cjs/lib/hooks/useCanvasEvents.js +31 -25
  32. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  33. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  34. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  35. package/dist-cjs/lib/{utils/nearestMultiple.js → hooks/useStateAttribute.js} +15 -14
  36. package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
  37. package/dist-cjs/lib/license/Watermark.js +6 -6
  38. package/dist-cjs/lib/license/Watermark.js.map +1 -1
  39. package/dist-cjs/lib/options.js +7 -0
  40. package/dist-cjs/lib/options.js.map +2 -2
  41. package/dist-cjs/lib/primitives/Box.js +3 -0
  42. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  43. package/dist-cjs/lib/utils/EditorAtom.js +45 -0
  44. package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
  45. package/dist-cjs/version.js +3 -3
  46. package/dist-cjs/version.js.map +1 -1
  47. package/dist-esm/index.d.mts +129 -9
  48. package/dist-esm/index.mjs +3 -1
  49. package/dist-esm/index.mjs.map +2 -2
  50. package/dist-esm/lib/TldrawEditor.mjs +8 -2
  51. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  52. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  53. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  54. package/dist-esm/lib/components/Shape.mjs +7 -10
  55. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  56. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
  57. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  58. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  59. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
  60. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  61. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  62. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  63. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  64. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  65. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  66. package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
  67. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  68. package/dist-esm/lib/editor/Editor.mjs +74 -34
  69. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  70. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +9 -4
  71. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  72. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  73. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  74. package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
  75. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  76. package/dist-esm/lib/hooks/useCanvasEvents.mjs +32 -26
  77. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  78. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  79. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  80. package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
  81. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
  82. package/dist-esm/lib/license/Watermark.mjs +6 -6
  83. package/dist-esm/lib/license/Watermark.mjs.map +1 -1
  84. package/dist-esm/lib/options.mjs +7 -0
  85. package/dist-esm/lib/options.mjs.map +2 -2
  86. package/dist-esm/lib/primitives/Box.mjs +4 -1
  87. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  88. package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
  89. package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
  90. package/dist-esm/version.mjs +3 -3
  91. package/dist-esm/version.mjs.map +1 -1
  92. package/editor.css +301 -288
  93. package/package.json +14 -37
  94. package/src/index.ts +2 -0
  95. package/src/lib/TldrawEditor.tsx +13 -6
  96. package/src/lib/components/MenuClickCapture.tsx +0 -8
  97. package/src/lib/components/Shape.tsx +6 -12
  98. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
  99. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  100. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  101. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  102. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
  103. package/src/lib/config/TLUserPreferences.ts +8 -1
  104. package/src/lib/editor/Editor.test.ts +12 -11
  105. package/src/lib/editor/Editor.ts +107 -68
  106. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  107. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  108. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  109. package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
  110. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  111. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  112. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  113. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  114. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  115. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +34 -26
  116. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +6 -1
  117. package/src/lib/editor/shapes/ShapeUtil.ts +35 -0
  118. package/src/lib/editor/types/misc-types.ts +54 -1
  119. package/src/lib/exports/getSvgJsx.test.ts +868 -0
  120. package/src/lib/exports/getSvgJsx.tsx +78 -21
  121. package/src/lib/hooks/useCanvasEvents.ts +45 -38
  122. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  123. package/src/lib/hooks/useStateAttribute.ts +15 -0
  124. package/src/lib/license/LicenseManager.test.ts +3 -1
  125. package/src/lib/license/Watermark.test.tsx +2 -1
  126. package/src/lib/license/Watermark.tsx +6 -6
  127. package/src/lib/options.ts +8 -0
  128. package/src/lib/primitives/Box.test.ts +126 -0
  129. package/src/lib/primitives/Box.ts +10 -1
  130. package/src/lib/utils/EditorAtom.ts +37 -0
  131. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  132. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  133. package/src/version.ts +3 -3
  134. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  135. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  136. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  137. package/src/lib/utils/nearestMultiple.ts +0 -13
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/config/TLUserPreferences.ts"],
4
- "sourcesContent": ["import { atom } from '@tldraw/state'\nimport { getDefaultTranslationLocale } from '@tldraw/tlschema'\nimport { getFromLocalStorage, setInLocalStorage, structuredClone, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\n\nconst USER_DATA_KEY = 'TLDRAW_USER_DATA_v3'\n\n/**\n * A user of tldraw\n *\n * @public\n */\nexport interface TLUserPreferences {\n\tid: string\n\tname?: string | null\n\tcolor?: string | null\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale?: string | null\n\tanimationSpeed?: number | null\n\tareKeyboardShortcutsEnabled?: boolean | null\n\tedgeScrollSpeed?: number | null\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\tisSnapMode?: boolean | null\n\tisWrapMode?: boolean | null\n\tisDynamicSizeMode?: boolean | null\n\tisPasteAtCursorMode?: boolean | null\n}\n\ninterface UserDataSnapshot {\n\tversion: number\n\tuser: TLUserPreferences\n}\n\ninterface UserChangeBroadcastMessage {\n\ttype: typeof broadcastEventKey\n\torigin: string\n\tdata: UserDataSnapshot\n}\n\n/** @public */\nexport const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUserPreferences>({\n\tid: T.string,\n\tname: T.string.nullable().optional(),\n\tcolor: T.string.nullable().optional(),\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale: T.string.nullable().optional(),\n\tanimationSpeed: T.number.nullable().optional(),\n\tareKeyboardShortcutsEnabled: T.boolean.nullable().optional(),\n\tedgeScrollSpeed: T.number.nullable().optional(),\n\tcolorScheme: T.literalEnum('light', 'dark', 'system').optional(),\n\tisSnapMode: T.boolean.nullable().optional(),\n\tisWrapMode: T.boolean.nullable().optional(),\n\tisDynamicSizeMode: T.boolean.nullable().optional(),\n\tisPasteAtCursorMode: T.boolean.nullable().optional(),\n})\n\nconst Versions = {\n\tAddAnimationSpeed: 1,\n\tAddIsSnapMode: 2,\n\tMakeFieldsNullable: 3,\n\tAddEdgeScrollSpeed: 4,\n\tAddExcalidrawSelectMode: 5,\n\tAddDynamicSizeMode: 6,\n\tAllowSystemColorScheme: 7,\n\tAddPasteAtCursor: 8,\n\tAddKeyboardShortcuts: 9,\n} as const\n\nconst CURRENT_VERSION = Math.max(...Object.values(Versions))\n\nfunction migrateSnapshot(data: { version: number; user: any }) {\n\tif (data.version < Versions.AddAnimationSpeed) {\n\t\tdata.user.animationSpeed = 1\n\t}\n\tif (data.version < Versions.AddIsSnapMode) {\n\t\tdata.user.isSnapMode = false\n\t}\n\tif (data.version < Versions.MakeFieldsNullable) {\n\t\t// noop\n\t}\n\tif (data.version < Versions.AddEdgeScrollSpeed) {\n\t\tdata.user.edgeScrollSpeed = 1\n\t}\n\tif (data.version < Versions.AddExcalidrawSelectMode) {\n\t\tdata.user.isWrapMode = false\n\t}\n\tif (data.version < Versions.AllowSystemColorScheme) {\n\t\tif (data.user.isDarkMode === true) {\n\t\t\tdata.user.colorScheme = 'dark'\n\t\t} else if (data.user.isDarkMode === false) {\n\t\t\tdata.user.colorScheme = 'light'\n\t\t}\n\t\tdelete data.user.isDarkMode\n\t}\n\n\tif (data.version < Versions.AddDynamicSizeMode) {\n\t\tdata.user.isDynamicSizeMode = false\n\t}\n\tif (data.version < Versions.AddPasteAtCursor) {\n\t\tdata.user.isPasteAtCursorMode = false\n\t}\n\tif (data.version < Versions.AddKeyboardShortcuts) {\n\t\tdata.user.areKeyboardShortcutsEnabled = true\n\t}\n\n\t// finally\n\tdata.version = CURRENT_VERSION\n}\n\n/** @internal */\nexport const USER_COLORS = [\n\t'#FF802B',\n\t'#EC5E41',\n\t'#F2555A',\n\t'#F04F88',\n\t'#E34BA9',\n\t'#BD54C6',\n\t'#9D5BD2',\n\t'#7B66DC',\n\t'#02B1CC',\n\t'#11B3A3',\n\t'#39B178',\n\t'#55B467',\n] as const\n\nfunction getRandomColor() {\n\treturn USER_COLORS[Math.floor(Math.random() * USER_COLORS.length)]\n}\n\n/** @internal */\nexport function userPrefersReducedMotion() {\n\tif (typeof window !== 'undefined' && 'matchMedia' in window) {\n\t\treturn window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false\n\t}\n\n\treturn false\n}\n\n/** @public */\nexport const defaultUserPreferences = Object.freeze({\n\tname: '',\n\tlocale: getDefaultTranslationLocale(),\n\tcolor: getRandomColor(),\n\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tedgeScrollSpeed: 1,\n\tanimationSpeed: userPrefersReducedMotion() ? 0 : 1,\n\tareKeyboardShortcutsEnabled: true,\n\tisSnapMode: false,\n\tisWrapMode: false,\n\tisDynamicSizeMode: false,\n\tisPasteAtCursorMode: false,\n\tcolorScheme: 'light',\n}) satisfies Readonly<Omit<TLUserPreferences, 'id'>>\n\n/** @public */\nexport function getFreshUserPreferences(): TLUserPreferences {\n\treturn {\n\t\tid: uniqueId(),\n\t\tcolor: getRandomColor(),\n\t}\n}\n\nfunction migrateUserPreferences(userData: unknown): TLUserPreferences {\n\tif (userData === null || typeof userData !== 'object') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tif (!('version' in userData) || !('user' in userData) || typeof userData.version !== 'number') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tconst snapshot = structuredClone(userData) as any\n\n\tmigrateSnapshot(snapshot)\n\n\ttry {\n\t\treturn userTypeValidator.validate(snapshot.user)\n\t} catch {\n\t\treturn getFreshUserPreferences()\n\t}\n}\n\nfunction loadUserPreferences(): TLUserPreferences {\n\tconst userData = (JSON.parse(getFromLocalStorage(USER_DATA_KEY) || 'null') ??\n\t\tnull) as null | UserDataSnapshot\n\n\treturn migrateUserPreferences(userData)\n}\n\nconst globalUserPreferences = atom<TLUserPreferences | null>('globalUserData', null)\n\nfunction storeUserPreferences() {\n\tsetInLocalStorage(\n\t\tUSER_DATA_KEY,\n\t\tJSON.stringify({\n\t\t\tversion: CURRENT_VERSION,\n\t\t\tuser: globalUserPreferences.get(),\n\t\t})\n\t)\n}\n\n/** @public */\nexport function setUserPreferences(user: TLUserPreferences) {\n\tuserTypeValidator.validate(user)\n\tglobalUserPreferences.set(user)\n\tstoreUserPreferences()\n\tbroadcastUserPreferencesChange()\n}\n\nconst isTest = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\nconst channel =\n\ttypeof BroadcastChannel !== 'undefined' && !isTest\n\t\t? new BroadcastChannel('tldraw-user-sync')\n\t\t: null\n\nchannel?.addEventListener('message', (e) => {\n\tconst data = e.data as undefined | UserChangeBroadcastMessage\n\tif (data?.type === broadcastEventKey && data?.origin !== getBroadcastOrigin()) {\n\t\tglobalUserPreferences.set(migrateUserPreferences(data.data))\n\t}\n})\n\nlet _broadcastOrigin = null as null | string\nfunction getBroadcastOrigin() {\n\tif (_broadcastOrigin === null) {\n\t\t_broadcastOrigin = uniqueId()\n\t}\n\treturn _broadcastOrigin\n}\nconst broadcastEventKey = 'tldraw-user-preferences-change' as const\n\nfunction broadcastUserPreferencesChange() {\n\tchannel?.postMessage({\n\t\ttype: broadcastEventKey,\n\t\torigin: getBroadcastOrigin(),\n\t\tdata: {\n\t\t\tuser: getUserPreferences(),\n\t\t\tversion: CURRENT_VERSION,\n\t\t},\n\t} satisfies UserChangeBroadcastMessage)\n}\n\n/** @public */\nexport function getUserPreferences(): TLUserPreferences {\n\tlet prefs = globalUserPreferences.get()\n\tif (!prefs) {\n\t\tprefs = loadUserPreferences()\n\t\tsetUserPreferences(prefs)\n\t}\n\treturn prefs\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { atom } from '@tldraw/state'\nimport { getDefaultTranslationLocale } from '@tldraw/tlschema'\nimport { getFromLocalStorage, setInLocalStorage, structuredClone, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\n\nconst USER_DATA_KEY = 'TLDRAW_USER_DATA_v3'\n\n/**\n * A user of tldraw\n *\n * @public\n */\nexport interface TLUserPreferences {\n\tid: string\n\tname?: string | null\n\tcolor?: string | null\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale?: string | null\n\tanimationSpeed?: number | null\n\tareKeyboardShortcutsEnabled?: boolean | null\n\tedgeScrollSpeed?: number | null\n\tcolorScheme?: 'light' | 'dark' | 'system'\n\tisSnapMode?: boolean | null\n\tisWrapMode?: boolean | null\n\tisDynamicSizeMode?: boolean | null\n\tisPasteAtCursorMode?: boolean | null\n\tshowUiLabels?: boolean | null\n}\n\ninterface UserDataSnapshot {\n\tversion: number\n\tuser: TLUserPreferences\n}\n\ninterface UserChangeBroadcastMessage {\n\ttype: typeof broadcastEventKey\n\torigin: string\n\tdata: UserDataSnapshot\n}\n\n/** @public */\nexport const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUserPreferences>({\n\tid: T.string,\n\tname: T.string.nullable().optional(),\n\tcolor: T.string.nullable().optional(),\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tlocale: T.string.nullable().optional(),\n\tanimationSpeed: T.number.nullable().optional(),\n\tareKeyboardShortcutsEnabled: T.boolean.nullable().optional(),\n\tedgeScrollSpeed: T.number.nullable().optional(),\n\tcolorScheme: T.literalEnum('light', 'dark', 'system').optional(),\n\tisSnapMode: T.boolean.nullable().optional(),\n\tisWrapMode: T.boolean.nullable().optional(),\n\tisDynamicSizeMode: T.boolean.nullable().optional(),\n\tisPasteAtCursorMode: T.boolean.nullable().optional(),\n\tshowUiLabels: T.boolean.nullable().optional(),\n})\n\nconst Versions = {\n\tAddAnimationSpeed: 1,\n\tAddIsSnapMode: 2,\n\tMakeFieldsNullable: 3,\n\tAddEdgeScrollSpeed: 4,\n\tAddExcalidrawSelectMode: 5,\n\tAddDynamicSizeMode: 6,\n\tAllowSystemColorScheme: 7,\n\tAddPasteAtCursor: 8,\n\tAddKeyboardShortcuts: 9,\n\tAddShowUiLabels: 10,\n} as const\n\nconst CURRENT_VERSION = Math.max(...Object.values(Versions))\n\nfunction migrateSnapshot(data: { version: number; user: any }) {\n\tif (data.version < Versions.AddAnimationSpeed) {\n\t\tdata.user.animationSpeed = 1\n\t}\n\tif (data.version < Versions.AddIsSnapMode) {\n\t\tdata.user.isSnapMode = false\n\t}\n\tif (data.version < Versions.MakeFieldsNullable) {\n\t\t// noop\n\t}\n\tif (data.version < Versions.AddEdgeScrollSpeed) {\n\t\tdata.user.edgeScrollSpeed = 1\n\t}\n\tif (data.version < Versions.AddExcalidrawSelectMode) {\n\t\tdata.user.isWrapMode = false\n\t}\n\tif (data.version < Versions.AllowSystemColorScheme) {\n\t\tif (data.user.isDarkMode === true) {\n\t\t\tdata.user.colorScheme = 'dark'\n\t\t} else if (data.user.isDarkMode === false) {\n\t\t\tdata.user.colorScheme = 'light'\n\t\t}\n\t\tdelete data.user.isDarkMode\n\t}\n\n\tif (data.version < Versions.AddDynamicSizeMode) {\n\t\tdata.user.isDynamicSizeMode = false\n\t}\n\tif (data.version < Versions.AddPasteAtCursor) {\n\t\tdata.user.isPasteAtCursorMode = false\n\t}\n\tif (data.version < Versions.AddKeyboardShortcuts) {\n\t\tdata.user.areKeyboardShortcutsEnabled = true\n\t}\n\tif (data.version < Versions.AddShowUiLabels) {\n\t\tdata.user.showUiLabels = false\n\t}\n\n\t// finally\n\tdata.version = CURRENT_VERSION\n}\n\n/** @internal */\nexport const USER_COLORS = [\n\t'#FF802B',\n\t'#EC5E41',\n\t'#F2555A',\n\t'#F04F88',\n\t'#E34BA9',\n\t'#BD54C6',\n\t'#9D5BD2',\n\t'#7B66DC',\n\t'#02B1CC',\n\t'#11B3A3',\n\t'#39B178',\n\t'#55B467',\n] as const\n\nfunction getRandomColor() {\n\treturn USER_COLORS[Math.floor(Math.random() * USER_COLORS.length)]\n}\n\n/** @internal */\nexport function userPrefersReducedMotion() {\n\tif (typeof window !== 'undefined' && window.matchMedia) {\n\t\treturn window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false\n\t}\n\n\treturn false\n}\n\n/** @public */\nexport const defaultUserPreferences = Object.freeze({\n\tname: '',\n\tlocale: getDefaultTranslationLocale(),\n\tcolor: getRandomColor(),\n\n\t// N.B. These are duplicated in TLdrawAppUser.\n\tedgeScrollSpeed: 1,\n\tanimationSpeed: userPrefersReducedMotion() ? 0 : 1,\n\tareKeyboardShortcutsEnabled: true,\n\tisSnapMode: false,\n\tisWrapMode: false,\n\tisDynamicSizeMode: false,\n\tisPasteAtCursorMode: false,\n\tshowUiLabels: false,\n\tcolorScheme: 'light',\n}) satisfies Readonly<Omit<TLUserPreferences, 'id'>>\n\n/** @public */\nexport function getFreshUserPreferences(): TLUserPreferences {\n\treturn {\n\t\tid: uniqueId(),\n\t\tcolor: getRandomColor(),\n\t}\n}\n\nfunction migrateUserPreferences(userData: unknown): TLUserPreferences {\n\tif (userData === null || typeof userData !== 'object') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tif (!('version' in userData) || !('user' in userData) || typeof userData.version !== 'number') {\n\t\treturn getFreshUserPreferences()\n\t}\n\n\tconst snapshot = structuredClone(userData) as any\n\n\tmigrateSnapshot(snapshot)\n\n\ttry {\n\t\treturn userTypeValidator.validate(snapshot.user)\n\t} catch {\n\t\treturn getFreshUserPreferences()\n\t}\n}\n\nfunction loadUserPreferences(): TLUserPreferences {\n\tconst userData = (JSON.parse(getFromLocalStorage(USER_DATA_KEY) || 'null') ??\n\t\tnull) as null | UserDataSnapshot\n\n\treturn migrateUserPreferences(userData)\n}\n\nconst globalUserPreferences = atom<TLUserPreferences | null>('globalUserData', null)\n\nfunction storeUserPreferences() {\n\tsetInLocalStorage(\n\t\tUSER_DATA_KEY,\n\t\tJSON.stringify({\n\t\t\tversion: CURRENT_VERSION,\n\t\t\tuser: globalUserPreferences.get(),\n\t\t})\n\t)\n}\n\n/** @public */\nexport function setUserPreferences(user: TLUserPreferences) {\n\tuserTypeValidator.validate(user)\n\tglobalUserPreferences.set(user)\n\tstoreUserPreferences()\n\tbroadcastUserPreferencesChange()\n}\n\nconst isTest = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\nconst channel =\n\ttypeof BroadcastChannel !== 'undefined' && !isTest\n\t\t? new BroadcastChannel('tldraw-user-sync')\n\t\t: null\n\nchannel?.addEventListener('message', (e) => {\n\tconst data = e.data as undefined | UserChangeBroadcastMessage\n\tif (data?.type === broadcastEventKey && data?.origin !== getBroadcastOrigin()) {\n\t\tglobalUserPreferences.set(migrateUserPreferences(data.data))\n\t}\n})\n\nlet _broadcastOrigin = null as null | string\nfunction getBroadcastOrigin() {\n\tif (_broadcastOrigin === null) {\n\t\t_broadcastOrigin = uniqueId()\n\t}\n\treturn _broadcastOrigin\n}\nconst broadcastEventKey = 'tldraw-user-preferences-change' as const\n\nfunction broadcastUserPreferencesChange() {\n\tchannel?.postMessage({\n\t\ttype: broadcastEventKey,\n\t\torigin: getBroadcastOrigin(),\n\t\tdata: {\n\t\t\tuser: getUserPreferences(),\n\t\t\tversion: CURRENT_VERSION,\n\t\t},\n\t} satisfies UserChangeBroadcastMessage)\n}\n\n/** @public */\nexport function getUserPreferences(): TLUserPreferences {\n\tlet prefs = globalUserPreferences.get()\n\tif (!prefs) {\n\t\tprefs = loadUserPreferences()\n\t\tsetUserPreferences(prefs)\n\t}\n\treturn prefs\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3700,16 +3700,17 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3700
3700
  _getShapeMaskCache() {
3701
3701
  return this.store.createComputedCache("pageMaskCache", (shape) => {
3702
3702
  if (isPageId(shape.parentId)) return void 0;
3703
- const frameAncestors = this.getShapeAncestors(shape.id).filter(
3704
- (shape2) => this.isShapeOfType(shape2, "frame")
3705
- );
3706
- if (frameAncestors.length === 0) return void 0;
3707
- const pageMask = frameAncestors.map((s) => {
3708
- const geometry = this.getShapeGeometry(s.id);
3709
- const pageTransform = this.getShapePageTransform(s.id);
3710
- return pageTransform.applyToPoints(geometry.vertices);
3711
- }).reduce((acc, b) => {
3712
- if (!(b && acc)) return void 0;
3703
+ const clipPaths = [];
3704
+ for (const ancestor of this.getShapeAncestors(shape.id)) {
3705
+ const util = this.getShapeUtil(ancestor);
3706
+ const clipPath = util.getClipPath?.(ancestor);
3707
+ if (!clipPath) continue;
3708
+ if (util.shouldClipChild?.(shape) === false) continue;
3709
+ const pageTransform = this.getShapePageTransform(ancestor.id);
3710
+ clipPaths.push(pageTransform.applyToPoints(clipPath));
3711
+ }
3712
+ if (clipPaths.length === 0) return void 0;
3713
+ const pageMask = clipPaths.reduce((acc, b) => {
3713
3714
  const intersection = intersectPolygonPolygon(acc, b);
3714
3715
  if (intersection) {
3715
3716
  return intersection.map(Vec.Cast);
@@ -3944,6 +3945,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3944
3945
  hitInside = false,
3945
3946
  hitFrameInside = false
3946
3947
  } = opts;
3948
+ const [innerMargin, outerMargin] = Array.isArray(margin) ? margin : [margin, margin];
3947
3949
  let inHollowSmallestArea = Infinity;
3948
3950
  let inHollowSmallestAreaHit = null;
3949
3951
  let inMarginClosestToEdgeDistance = Infinity;
@@ -3953,7 +3955,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3953
3955
  return false;
3954
3956
  const pageMask = this.getShapeMask(shape);
3955
3957
  if (pageMask && !pointInPolygon(point, pageMask)) return false;
3956
- if (filter) return filter(shape);
3958
+ if (filter && !filter(shape)) return false;
3957
3959
  return true;
3958
3960
  });
3959
3961
  for (let i = shapesToCheck.length - 1; i >= 0; i--) {
@@ -3969,8 +3971,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3969
3971
  }
3970
3972
  }
3971
3973
  if (this.isShapeOfType(shape, "frame")) {
3972
- const distance2 = geometry.distanceToPoint(pointInShapeSpace, hitInside);
3973
- if (Math.abs(distance2) <= margin) {
3974
+ const distance2 = geometry.distanceToPoint(pointInShapeSpace, hitFrameInside);
3975
+ if (hitFrameInside ? distance2 > 0 && distance2 <= outerMargin || distance2 <= 0 && distance2 > -innerMargin : distance2 > 0 && distance2 <= outerMargin) {
3974
3976
  return inMarginClosestToEdgeHit || shape;
3975
3977
  }
3976
3978
  if (geometry.hitTestPoint(pointInShapeSpace, 0, true)) {
@@ -3990,10 +3992,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3990
3992
  }
3991
3993
  distance = minDistance;
3992
3994
  } else {
3993
- if (margin === 0 && (geometry.bounds.w < 1 || geometry.bounds.h < 1)) {
3995
+ if (outerMargin === 0 && (geometry.bounds.w < 1 || geometry.bounds.h < 1)) {
3994
3996
  distance = geometry.distanceToPoint(pointInShapeSpace, hitInside);
3995
3997
  } else {
3996
- if (geometry.bounds.containsPoint(pointInShapeSpace, margin)) {
3998
+ if (geometry.bounds.containsPoint(pointInShapeSpace, outerMargin)) {
3997
3999
  distance = geometry.distanceToPoint(pointInShapeSpace, hitInside);
3998
4000
  } else {
3999
4001
  distance = Infinity;
@@ -4001,12 +4003,22 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4001
4003
  }
4002
4004
  }
4003
4005
  if (geometry.isClosed) {
4004
- if (distance <= margin) {
4006
+ if (distance <= outerMargin || hitInside && distance <= 0 && distance > -innerMargin) {
4005
4007
  if (geometry.isFilled || isGroup && geometry.children[0].isFilled) {
4006
4008
  return inMarginClosestToEdgeHit || shape;
4007
4009
  } else {
4008
4010
  if (this.getShapePageBounds(shape).contains(viewportPageBounds)) continue;
4009
- if (Math.abs(distance) < margin) {
4011
+ if (hitInside ? (
4012
+ // On hitInside, the distance will be negative for hits inside
4013
+ // If the distance is positive, check against the outer margin
4014
+ (// If the distance is negative, check against the inner margin
4015
+ distance > 0 && distance <= outerMargin || distance <= 0 && distance > -innerMargin)
4016
+ ) : (
4017
+ // If hitInside is false, then sadly _we do not know_ whether the
4018
+ // point is inside or outside of the shape, so we check against
4019
+ // the max of the two margins
4020
+ (Math.abs(distance) <= Math.max(innerMargin, outerMargin))
4021
+ )) {
4010
4022
  if (Math.abs(distance) < inMarginClosestToEdgeDistance) {
4011
4023
  inMarginClosestToEdgeDistance = Math.abs(distance);
4012
4024
  inMarginClosestToEdgeHit = shape;
@@ -4771,7 +4783,16 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4771
4783
  }
4772
4784
  this.createShapes(shapesToCreate);
4773
4785
  this.createBindings(bindingsToCreate);
4774
- this.setSelectedShapes(compact(ids.map((id) => shapeIds.get(id))));
4786
+ this.setSelectedShapes(
4787
+ compact(
4788
+ ids.map((oldId) => {
4789
+ const newId = shapeIds.get(oldId);
4790
+ if (!newId) return null;
4791
+ if (!this.getShape(newId)) return null;
4792
+ return newId;
4793
+ })
4794
+ )
4795
+ );
4775
4796
  if (offset !== void 0) {
4776
4797
  const selectionPageBounds = this.getSelectionPageBounds();
4777
4798
  const viewportPageBounds = this.getViewportPageBounds();
@@ -5525,8 +5546,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5525
5546
  const shapesMovingTogether = [shape];
5526
5547
  const boundsOfShapesMovingTogether = [shapePageBounds];
5527
5548
  if (!this.getShapeUtil(shape).canBeLaidOut?.(shape, {
5528
- type: "stretch",
5529
- shapes: shapesToStretchFirstPass
5549
+ type: "stretch"
5530
5550
  })) {
5531
5551
  continue;
5532
5552
  }
@@ -5851,21 +5871,24 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5851
5871
  }
5852
5872
  if (!partial.parentId || !(this.store.has(partial.parentId) || shapes.some((p) => p.id === partial.parentId))) {
5853
5873
  let parentId = this.getFocusedGroupId();
5854
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5855
- const parent = currentPageShapesSorted[i];
5856
- const util = this.getShapeUtil(parent);
5857
- if (util.canReceiveNewChildrenOfType(parent, partial.type) && !this.isShapeHidden(parent) && this.isPointInShape(
5858
- parent,
5859
- // If no parent is provided, then we can treat the
5860
- // shape's provided x/y as being in the page's space.
5861
- { x: partial.x ?? 0, y: partial.y ?? 0 },
5862
- {
5863
- margin: 0,
5864
- hitInside: true
5874
+ const isPositioned = partial.x !== void 0 && partial.y !== void 0;
5875
+ if (isPositioned) {
5876
+ for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5877
+ const parent = currentPageShapesSorted[i];
5878
+ const util = this.getShapeUtil(parent);
5879
+ if (util.canReceiveNewChildrenOfType(parent, partial.type) && !this.isShapeHidden(parent) && this.isPointInShape(
5880
+ parent,
5881
+ // If no parent is provided, then we can treat the
5882
+ // shape's provided x/y as being in the page's space.
5883
+ { x: partial.x ?? 0, y: partial.y ?? 0 },
5884
+ {
5885
+ margin: 0,
5886
+ hitInside: true
5887
+ }
5888
+ )) {
5889
+ parentId = parent.id;
5890
+ break;
5865
5891
  }
5866
- )) {
5867
- parentId = parent.id;
5868
- break;
5869
5892
  }
5870
5893
  }
5871
5894
  const prevParentId = partial.parentId;
@@ -6954,6 +6977,23 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6954
6977
  }
6955
6978
  }
6956
6979
  }
6980
+ /**
6981
+ * Get an exported image of the given shapes as a data URL.
6982
+ *
6983
+ * @param shapes - The shapes (or shape ids) to export.
6984
+ * @param opts - Options for the export.
6985
+ *
6986
+ * @returns A data URL of the image.
6987
+ * @public
6988
+ */
6989
+ async toImageDataUrl(shapes, opts = {}) {
6990
+ const { blob, width, height } = await this.toImage(shapes, opts);
6991
+ return {
6992
+ url: await FileHelpers.blobToDataUrl(blob),
6993
+ width,
6994
+ height
6995
+ };
6996
+ }
6957
6997
  /**
6958
6998
  * Update the input points from a pointer, pinch, or wheel event.
6959
6999
  *