@tldraw/editor 3.11.0-canary.f529c521e249 → 3.12.0-canary.17a260baed4f

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 (93) hide show
  1. package/CHANGELOG.md +93 -2
  2. package/dist-cjs/index.d.ts +23 -9
  3. package/dist-cjs/index.js +1 -1
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +4 -4
  6. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +34 -26
  8. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
  9. package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
  10. package/dist-cjs/lib/config/TLUserPreferences.js.map +1 -1
  11. package/dist-cjs/lib/config/createTLStore.js +2 -1
  12. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  13. package/dist-cjs/lib/constants.js +1 -1
  14. package/dist-cjs/lib/constants.js.map +2 -2
  15. package/dist-cjs/lib/editor/Editor.js +18 -14
  16. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  17. package/dist-cjs/lib/editor/managers/FocusManager.js +15 -0
  18. package/dist-cjs/lib/editor/managers/FocusManager.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js +1 -1
  20. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +2 -2
  21. package/dist-cjs/lib/exports/StyleEmbedder.js +16 -1
  22. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  23. package/dist-cjs/lib/exports/exportToSvg.js.map +1 -1
  24. package/dist-cjs/lib/exports/getSvgJsx.js +1 -1
  25. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  26. package/dist-cjs/lib/exports/parseCss.js +27 -2
  27. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  28. package/dist-cjs/lib/hooks/useLocalStore.js +3 -0
  29. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  30. package/dist-cjs/lib/license/Watermark.js +7 -1
  31. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  32. package/dist-cjs/lib/options.js +2 -1
  33. package/dist-cjs/lib/options.js.map +2 -2
  34. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +8 -0
  35. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js.map +2 -2
  36. package/dist-cjs/version.js +3 -3
  37. package/dist-cjs/version.js.map +1 -1
  38. package/dist-esm/index.d.mts +23 -9
  39. package/dist-esm/index.mjs +4 -2
  40. package/dist-esm/index.mjs.map +2 -2
  41. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +4 -4
  42. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  43. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +34 -26
  44. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
  45. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
  46. package/dist-esm/lib/config/TLUserPreferences.mjs.map +1 -1
  47. package/dist-esm/lib/config/createTLStore.mjs +2 -1
  48. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  49. package/dist-esm/lib/constants.mjs +1 -1
  50. package/dist-esm/lib/constants.mjs.map +2 -2
  51. package/dist-esm/lib/editor/Editor.mjs +18 -14
  52. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  53. package/dist-esm/lib/editor/managers/FocusManager.mjs +15 -0
  54. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs +1 -1
  56. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +2 -2
  57. package/dist-esm/lib/exports/StyleEmbedder.mjs +22 -2
  58. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  59. package/dist-esm/lib/exports/exportToSvg.mjs.map +1 -1
  60. package/dist-esm/lib/exports/getSvgJsx.mjs +1 -1
  61. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  62. package/dist-esm/lib/exports/parseCss.mjs +27 -2
  63. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  64. package/dist-esm/lib/hooks/useLocalStore.mjs +3 -0
  65. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  66. package/dist-esm/lib/license/Watermark.mjs +7 -1
  67. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  68. package/dist-esm/lib/options.mjs +2 -1
  69. package/dist-esm/lib/options.mjs.map +2 -2
  70. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +8 -0
  71. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
  72. package/dist-esm/version.mjs +3 -3
  73. package/dist-esm/version.mjs.map +1 -1
  74. package/editor.css +11 -1
  75. package/package.json +10 -7
  76. package/src/index.ts +4 -1
  77. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +4 -4
  78. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +52 -31
  79. package/src/lib/config/TLUserPreferences.ts +1 -1
  80. package/src/lib/config/createTLStore.ts +1 -0
  81. package/src/lib/constants.ts +1 -1
  82. package/src/lib/editor/Editor.ts +20 -17
  83. package/src/lib/editor/managers/FocusManager.ts +18 -0
  84. package/src/lib/editor/managers/UserPreferencesManager.ts +1 -1
  85. package/src/lib/exports/StyleEmbedder.ts +23 -4
  86. package/src/lib/exports/exportToSvg.tsx +1 -1
  87. package/src/lib/exports/getSvgJsx.tsx +1 -1
  88. package/src/lib/exports/parseCss.ts +36 -2
  89. package/src/lib/hooks/useLocalStore.ts +3 -0
  90. package/src/lib/license/Watermark.tsx +7 -1
  91. package/src/lib/options.ts +6 -0
  92. package/src/lib/utils/sync/LocalIndexedDb.ts +9 -0
  93. package/src/version.ts +3 -3
@@ -14,6 +14,8 @@ class FocusManager {
14
14
  editor.updateInstanceState({ isFocused: !!autoFocus });
15
15
  }
16
16
  this.updateContainerClass();
17
+ document.body.addEventListener("keydown", this.handleKeyDown.bind(this));
18
+ document.body.addEventListener("mousedown", this.handleMouseDown.bind(this));
17
19
  }
18
20
  disposeSideEffectListener;
19
21
  /**
@@ -33,6 +35,17 @@ class FocusManager {
33
35
  } else {
34
36
  container.classList.remove("tl-container__focused");
35
37
  }
38
+ container.classList.add("tl-container__no-focus-ring");
39
+ }
40
+ handleKeyDown(keyEvent) {
41
+ const container = this.editor.getContainer();
42
+ if (keyEvent.key === "Tab") {
43
+ container.classList.remove("tl-container__no-focus-ring");
44
+ }
45
+ }
46
+ handleMouseDown() {
47
+ const container = this.editor.getContainer();
48
+ container.classList.add("tl-container__no-focus-ring");
36
49
  }
37
50
  focus() {
38
51
  this.editor.getContainer().focus();
@@ -42,6 +55,8 @@ class FocusManager {
42
55
  this.editor.getContainer().blur();
43
56
  }
44
57
  dispose() {
58
+ document.body.removeEventListener("keydown", this.handleKeyDown.bind(this));
59
+ document.body.removeEventListener("mousedown", this.handleMouseDown.bind(this));
45
60
  this.disposeSideEffectListener?.();
46
61
  }
47
62
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/managers/FocusManager.ts"],
4
- "sourcesContent": ["import type { Editor } from '../Editor'\n\n/**\n * A manager for ensuring correct focus across the editor.\n * It will listen for changes in the instance state to make sure the\n * container is focused when the editor is focused.\n * Also, it will make sure that the focus is on things like text\n * labels when the editor is in editing mode.\n *\n * @internal\n */\nexport class FocusManager {\n\tprivate disposeSideEffectListener?: () => void\n\n\tconstructor(\n\t\tpublic editor: Editor,\n\t\tautoFocus?: boolean\n\t) {\n\t\tthis.disposeSideEffectListener = editor.sideEffects.registerAfterChangeHandler(\n\t\t\t'instance',\n\t\t\t(prev, next) => {\n\t\t\t\tif (prev.isFocused !== next.isFocused) {\n\t\t\t\t\tthis.updateContainerClass()\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\n\t\tconst currentFocusState = editor.getInstanceState().isFocused\n\t\tif (autoFocus !== currentFocusState) {\n\t\t\teditor.updateInstanceState({ isFocused: !!autoFocus })\n\t\t}\n\t\tthis.updateContainerClass()\n\t}\n\n\t/**\n\t * The editor's focus state and the container's focus state\n\t * are not necessarily always in sync. For that reason we\n\t * can't rely on the css `:focus` or `:focus-within` selectors to style the\n\t * editor when it is in focus.\n\t *\n\t * For that reason we synchronize the editor's focus state with a\n\t * special class on the container: tl-container__focused\n\t */\n\tprivate updateContainerClass() {\n\t\tconst container = this.editor.getContainer()\n\t\tconst instanceState = this.editor.getInstanceState()\n\n\t\tif (instanceState.isFocused) {\n\t\t\tcontainer.classList.add('tl-container__focused')\n\t\t} else {\n\t\t\tcontainer.classList.remove('tl-container__focused')\n\t\t}\n\t}\n\n\tfocus() {\n\t\tthis.editor.getContainer().focus()\n\t}\n\n\tblur() {\n\t\tthis.editor.complete() // stop any interaction\n\t\tthis.editor.getContainer().blur() // blur the container\n\t}\n\n\tdispose() {\n\t\tthis.disposeSideEffectListener?.()\n\t}\n}\n"],
5
- "mappings": "AAWO,MAAM,aAAa;AAAA,EAGzB,YACQ,QACP,WACC;AAFM;AAGP,SAAK,4BAA4B,OAAO,YAAY;AAAA,MACnD;AAAA,MACA,CAAC,MAAM,SAAS;AACf,YAAI,KAAK,cAAc,KAAK,WAAW;AACtC,eAAK,qBAAqB;AAAA,QAC3B;AAAA,MACD;AAAA,IACD;AAEA,UAAM,oBAAoB,OAAO,iBAAiB,EAAE;AACpD,QAAI,cAAc,mBAAmB;AACpC,aAAO,oBAAoB,EAAE,WAAW,CAAC,CAAC,UAAU,CAAC;AAAA,IACtD;AACA,SAAK,qBAAqB;AAAA,EAC3B;AAAA,EApBQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,uBAAuB;AAC9B,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,gBAAgB,KAAK,OAAO,iBAAiB;AAEnD,QAAI,cAAc,WAAW;AAC5B,gBAAU,UAAU,IAAI,uBAAuB;AAAA,IAChD,OAAO;AACN,gBAAU,UAAU,OAAO,uBAAuB;AAAA,IACnD;AAAA,EACD;AAAA,EAEA,QAAQ;AACP,SAAK,OAAO,aAAa,EAAE,MAAM;AAAA,EAClC;AAAA,EAEA,OAAO;AACN,SAAK,OAAO,SAAS;AACrB,SAAK,OAAO,aAAa,EAAE,KAAK;AAAA,EACjC;AAAA,EAEA,UAAU;AACT,SAAK,4BAA4B;AAAA,EAClC;AACD;",
4
+ "sourcesContent": ["import type { Editor } from '../Editor'\n\n/**\n * A manager for ensuring correct focus across the editor.\n * It will listen for changes in the instance state to make sure the\n * container is focused when the editor is focused.\n * Also, it will make sure that the focus is on things like text\n * labels when the editor is in editing mode.\n *\n * @internal\n */\nexport class FocusManager {\n\tprivate disposeSideEffectListener?: () => void\n\n\tconstructor(\n\t\tpublic editor: Editor,\n\t\tautoFocus?: boolean\n\t) {\n\t\tthis.disposeSideEffectListener = editor.sideEffects.registerAfterChangeHandler(\n\t\t\t'instance',\n\t\t\t(prev, next) => {\n\t\t\t\tif (prev.isFocused !== next.isFocused) {\n\t\t\t\t\tthis.updateContainerClass()\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\n\t\tconst currentFocusState = editor.getInstanceState().isFocused\n\t\tif (autoFocus !== currentFocusState) {\n\t\t\teditor.updateInstanceState({ isFocused: !!autoFocus })\n\t\t}\n\t\tthis.updateContainerClass()\n\n\t\tdocument.body.addEventListener('keydown', this.handleKeyDown.bind(this))\n\t\tdocument.body.addEventListener('mousedown', this.handleMouseDown.bind(this))\n\t}\n\n\t/**\n\t * The editor's focus state and the container's focus state\n\t * are not necessarily always in sync. For that reason we\n\t * can't rely on the css `:focus` or `:focus-within` selectors to style the\n\t * editor when it is in focus.\n\t *\n\t * For that reason we synchronize the editor's focus state with a\n\t * special class on the container: tl-container__focused\n\t */\n\tprivate updateContainerClass() {\n\t\tconst container = this.editor.getContainer()\n\t\tconst instanceState = this.editor.getInstanceState()\n\n\t\tif (instanceState.isFocused) {\n\t\t\tcontainer.classList.add('tl-container__focused')\n\t\t} else {\n\t\t\tcontainer.classList.remove('tl-container__focused')\n\t\t}\n\t\tcontainer.classList.add('tl-container__no-focus-ring')\n\t}\n\n\tprivate handleKeyDown(keyEvent: KeyboardEvent) {\n\t\tconst container = this.editor.getContainer()\n\t\tif (keyEvent.key === 'Tab') {\n\t\t\tcontainer.classList.remove('tl-container__no-focus-ring')\n\t\t}\n\t}\n\n\tprivate handleMouseDown() {\n\t\tconst container = this.editor.getContainer()\n\t\tcontainer.classList.add('tl-container__no-focus-ring')\n\t}\n\n\tfocus() {\n\t\tthis.editor.getContainer().focus()\n\t}\n\n\tblur() {\n\t\tthis.editor.complete() // stop any interaction\n\t\tthis.editor.getContainer().blur() // blur the container\n\t}\n\n\tdispose() {\n\t\tdocument.body.removeEventListener('keydown', this.handleKeyDown.bind(this))\n\t\tdocument.body.removeEventListener('mousedown', this.handleMouseDown.bind(this))\n\t\tthis.disposeSideEffectListener?.()\n\t}\n}\n"],
5
+ "mappings": "AAWO,MAAM,aAAa;AAAA,EAGzB,YACQ,QACP,WACC;AAFM;AAGP,SAAK,4BAA4B,OAAO,YAAY;AAAA,MACnD;AAAA,MACA,CAAC,MAAM,SAAS;AACf,YAAI,KAAK,cAAc,KAAK,WAAW;AACtC,eAAK,qBAAqB;AAAA,QAC3B;AAAA,MACD;AAAA,IACD;AAEA,UAAM,oBAAoB,OAAO,iBAAiB,EAAE;AACpD,QAAI,cAAc,mBAAmB;AACpC,aAAO,oBAAoB,EAAE,WAAW,CAAC,CAAC,UAAU,CAAC;AAAA,IACtD;AACA,SAAK,qBAAqB;AAE1B,aAAS,KAAK,iBAAiB,WAAW,KAAK,cAAc,KAAK,IAAI,CAAC;AACvE,aAAS,KAAK,iBAAiB,aAAa,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAAA,EAC5E;AAAA,EAvBQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,uBAAuB;AAC9B,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,gBAAgB,KAAK,OAAO,iBAAiB;AAEnD,QAAI,cAAc,WAAW;AAC5B,gBAAU,UAAU,IAAI,uBAAuB;AAAA,IAChD,OAAO;AACN,gBAAU,UAAU,OAAO,uBAAuB;AAAA,IACnD;AACA,cAAU,UAAU,IAAI,6BAA6B;AAAA,EACtD;AAAA,EAEQ,cAAc,UAAyB;AAC9C,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,QAAI,SAAS,QAAQ,OAAO;AAC3B,gBAAU,UAAU,OAAO,6BAA6B;AAAA,IACzD;AAAA,EACD;AAAA,EAEQ,kBAAkB;AACzB,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,cAAU,UAAU,IAAI,6BAA6B;AAAA,EACtD;AAAA,EAEA,QAAQ;AACP,SAAK,OAAO,aAAa,EAAE,MAAM;AAAA,EAClC;AAAA,EAEA,OAAO;AACN,SAAK,OAAO,SAAS;AACrB,SAAK,OAAO,aAAa,EAAE,KAAK;AAAA,EACjC;AAAA,EAEA,UAAU;AACT,aAAS,KAAK,oBAAoB,WAAW,KAAK,cAAc,KAAK,IAAI,CAAC;AAC1E,aAAS,KAAK,oBAAoB,aAAa,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAC9E,SAAK,4BAA4B;AAAA,EAClC;AACD;",
6
6
  "names": []
7
7
  }
@@ -117,7 +117,7 @@ class UserPreferencesManager {
117
117
  return this.user.userPreferences.get().id;
118
118
  }
119
119
  getName() {
120
- return this.user.userPreferences.get().name ?? defaultUserPreferences.name;
120
+ return this.user.userPreferences.get().name?.trim() ?? defaultUserPreferences.name;
121
121
  }
122
122
  getLocale() {
123
123
  return this.user.userPreferences.get().locale ?? defaultUserPreferences.locale;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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 ?? 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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",
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
6
  "names": []
7
7
  }
@@ -7,7 +7,12 @@ import {
7
7
  getRenderedChildren
8
8
  } from "./domUtils.mjs";
9
9
  import { resourceToDataUrl } from "./fetchCache.mjs";
10
- import { isPropertyInherited, parseCssValueUrls, shouldIncludeCssProperty } from "./parseCss.mjs";
10
+ import {
11
+ isPropertyCoveredByCurrentColor,
12
+ isPropertyInherited,
13
+ parseCssValueUrls,
14
+ shouldIncludeCssProperty
15
+ } from "./parseCss.mjs";
11
16
  const NO_STYLES = {};
12
17
  class StyleEmbedder {
13
18
  constructor(root) {
@@ -32,7 +37,19 @@ class StyleEmbedder {
32
37
  }
33
38
  readElementStyles(element, { shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }) {
34
39
  const defaultStyles = shouldRespectDefaults ? getDefaultStylesForTagName(element.tagName.toLowerCase()) : NO_STYLES;
35
- const parentStyles = shouldSkipInheritedParentStyles ? this.styles.get(element.parentElement)?.self ?? NO_STYLES : NO_STYLES;
40
+ const parentStyles = Object.assign({}, NO_STYLES);
41
+ if (shouldSkipInheritedParentStyles) {
42
+ let el = element.parentElement;
43
+ while (el) {
44
+ const currentStyles = this.styles.get(el)?.self;
45
+ for (const style in currentStyles) {
46
+ if (!parentStyles[style]) {
47
+ parentStyles[style] = currentStyles[style];
48
+ }
49
+ }
50
+ el = el.parentElement;
51
+ }
52
+ }
36
53
  const info = {
37
54
  self: styleFromElement(element, { defaultStyles, parentStyles }),
38
55
  before: styleFromPseudoElement(element, "::before"),
@@ -159,6 +176,8 @@ function styleFromComputedStyleMap(style, { defaultStyles, parentStyles }) {
159
176
  const value = style.get(property).toString();
160
177
  if (defaultStyles[property] === value) continue;
161
178
  if (parentStyles[property] === value && isPropertyInherited(property)) continue;
179
+ if (isPropertyCoveredByCurrentColor(style.get("color")?.toString() || "", property, value))
180
+ continue;
162
181
  styles[property] = value;
163
182
  }
164
183
  return styles;
@@ -170,6 +189,7 @@ function styleFromComputedStyle(style, { defaultStyles, parentStyles }) {
170
189
  const value = style.getPropertyValue(property);
171
190
  if (defaultStyles[property] === value) continue;
172
191
  if (parentStyles[property] === value && isPropertyInherited(property)) continue;
192
+ if (isPropertyCoveredByCurrentColor(style.color, property, value)) continue;
173
193
  styles[property] = value;
174
194
  }
175
195
  return styles;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/exports/StyleEmbedder.ts"],
4
- "sourcesContent": ["import { assertExists, objectMapValues, uniqueId } from '@tldraw/utils'\nimport { FontEmbedder } from './FontEmbedder'\nimport {\n\telementStyle,\n\tgetComputedStyle,\n\tgetRenderedChildNodes,\n\tgetRenderedChildren,\n} from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\nimport { isPropertyInherited, parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'\n\ntype Styles = { [K in string]?: string }\ntype ReadonlyStyles = { readonly [K in string]?: string }\nconst NO_STYLES = {} as const\n\ninterface ElementStyleInfo {\n\tself: Styles\n\tbefore: Styles | undefined\n\tafter: Styles | undefined\n}\n\nexport class StyleEmbedder {\n\tconstructor(private readonly root: Element) {}\n\tprivate readonly styles = new Map<Element, ElementStyleInfo>()\n\treadonly fonts = new FontEmbedder()\n\n\treadRootElementStyles(rootElement: Element) {\n\t\t// when reading a root, we always apply _all_ the styles, even if they match the defaults\n\t\tthis.readElementStyles(rootElement, {\n\t\t\tshouldRespectDefaults: false,\n\t\t\tshouldSkipInheritedParentStyles: false,\n\t\t})\n\n\t\tconst children = Array.from(getRenderedChildren(rootElement))\n\t\twhile (children.length) {\n\t\t\tconst child = children.pop()!\n\t\t\tchildren.push(...getRenderedChildren(child))\n\n\t\t\t// when reading children, we don't apply styles that match the defaults for that\n\t\t\t// element, or that would be inherited from the parent\n\t\t\tthis.readElementStyles(child, {\n\t\t\t\tshouldRespectDefaults: true,\n\t\t\t\tshouldSkipInheritedParentStyles: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate readElementStyles(\n\t\telement: Element,\n\t\t{ shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }\n\t) {\n\t\tconst defaultStyles = shouldRespectDefaults\n\t\t\t? getDefaultStylesForTagName(element.tagName.toLowerCase())\n\t\t\t: NO_STYLES\n\n\t\tconst parentStyles = shouldSkipInheritedParentStyles\n\t\t\t? (this.styles.get(element.parentElement as Element)?.self ?? NO_STYLES)\n\t\t\t: NO_STYLES\n\n\t\tconst info: ElementStyleInfo = {\n\t\t\tself: styleFromElement(element, { defaultStyles, parentStyles }),\n\t\t\tbefore: styleFromPseudoElement(element, '::before'),\n\t\t\tafter: styleFromPseudoElement(element, '::after'),\n\t\t}\n\t\tthis.styles.set(element, info)\n\t}\n\n\tfetchResources() {\n\t\tconst promises: Promise<void>[] = []\n\n\t\tfor (const info of this.styles.values()) {\n\t\t\tfor (const styles of objectMapValues(info)) {\n\t\t\t\tif (!styles) continue\n\t\t\t\tfor (const [property, value] of Object.entries(styles)) {\n\t\t\t\t\tif (!value) continue\n\t\t\t\t\tif (property === 'font-family') {\n\t\t\t\t\t\tthis.fonts.onFontFamilyValue(value)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst urlMatches = parseCssValueUrls(value)\n\t\t\t\t\tif (urlMatches.length === 0) continue\n\n\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t...urlMatches.map(async ({ url, original }) => {\n\t\t\t\t\t\t\tconst dataUrl = (await resourceToDataUrl(url)) ?? 'data:'\n\t\t\t\t\t\t\tstyles[property] = value.replace(original, `url(\"${dataUrl}\")`)\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Promise.all(promises)\n\t}\n\n\t// custom elements are tricky. if we serialize the dom as-is, the custom elements wont have\n\t// their shadow-dom contents serialized. after we've read all the styles, we need to unwrap the\n\t// contents of each custom elements shadow dom directly into the parent element itself.\n\tunwrapCustomElements() {\n\t\tconst visited = new Set<Node>()\n\n\t\tconst visit = (element: Element, clonedParent: Element | null) => {\n\t\t\tif (visited.has(element)) return\n\t\t\tvisited.add(element)\n\n\t\t\tconst shadowRoot = element.shadowRoot\n\n\t\t\tif (shadowRoot) {\n\t\t\t\tconst clonedCustomEl = document.createElement('div')\n\t\t\t\tthis.styles.set(clonedCustomEl, this.styles.get(element)!)\n\n\t\t\t\tclonedCustomEl.setAttribute('data-tl-custom-element', element.tagName)\n\t\t\t\t;(clonedParent ?? element.parentElement!).appendChild(clonedCustomEl)\n\n\t\t\t\tfor (const child of shadowRoot.childNodes) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedCustomEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedCustomEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.remove()\n\t\t\t} else if (clonedParent) {\n\t\t\t\tif (element.tagName.toLowerCase() === 'style') {\n\t\t\t\t\t// we don't clone style tags at that would break the style scoping. instead we\n\t\t\t\t\t// rely on the computed styles we've already read\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst clonedEl = element.cloneNode(false) as Element\n\t\t\t\tthis.styles.set(clonedEl, this.styles.get(element)!)\n\n\t\t\t\tclonedParent.appendChild(clonedEl)\n\n\t\t\t\tfor (const child of getRenderedChildNodes(element)) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const element of this.styles.keys()) {\n\t\t\tvisit(element, null)\n\t\t}\n\t}\n\n\tembedStyles(): string {\n\t\tlet css = ''\n\n\t\tfor (const [element, info] of this.styles) {\n\t\t\tif (info.after || info.before) {\n\t\t\t\tconst className = `pseudo-${uniqueId()}`\n\t\t\t\telement.classList.add(className)\n\n\t\t\t\tif (info.before) {\n\t\t\t\t\tcss += `.${className}::before {${formatCss(info.before)}}\\n`\n\t\t\t\t}\n\t\t\t\tif (info.after) {\n\t\t\t\t\tcss += `.${className}::after {${formatCss(info.after)}}\\n`\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst style = elementStyle(element)\n\t\t\tfor (const [property, value] of Object.entries(info.self)) {\n\t\t\t\tif (!value) continue\n\t\t\t\tstyle.setProperty(property, value)\n\t\t\t}\n\n\t\t\t// in HTML, font-kerning: auto is equivalent to font-kerning: normal. But in SVG, it's\n\t\t\t// none. We set it to normal here to match the HTML behavior, as otherwise this can\n\t\t\t// cause rendering differences.\n\t\t\tif (style.fontKerning === 'auto') {\n\t\t\t\tstyle.fontKerning = 'normal'\n\t\t\t}\n\t\t}\n\n\t\treturn css\n\t}\n\n\tasync getFontFaceCss() {\n\t\treturn await this.fonts.createCss()\n\t}\n\n\tdispose() {\n\t\tdestroyDefaultStyleFrame()\n\t}\n}\n\ninterface ReadStyleOpts {\n\tdefaultStyles: ReadonlyStyles\n\tparentStyles: ReadonlyStyles\n}\n\nfunction styleFromElement(element: Element, { defaultStyles, parentStyles }: ReadStyleOpts) {\n\t// `computedStyleMap` produces a more accurate representation of the styles, but it's not\n\t// supported in firefox at the time of writing. So we fall back to `getComputedStyle` if it's\n\t// not available.\n\tif (element.computedStyleMap) {\n\t\treturn styleFromComputedStyleMap(element.computedStyleMap(), { defaultStyles, parentStyles })\n\t}\n\treturn styleFromComputedStyle(getComputedStyle(element), { defaultStyles, parentStyles })\n}\n\nfunction styleFromPseudoElement(element: Element, pseudo: string) {\n\t// the equivalent of `computedStyleMap` for pseudo-elements isn't even fully specced out yet, so\n\t// for those we have to use `getComputedStyle` in all browsers.\n\tconst style = getComputedStyle(element, pseudo)\n\n\tconst content = style.getPropertyValue('content')\n\tif (content === '' || content === 'none') {\n\t\treturn undefined\n\t}\n\n\treturn styleFromComputedStyle(style, { defaultStyles: NO_STYLES, parentStyles: NO_STYLES })\n}\n\nfunction styleFromComputedStyleMap(\n\tstyle: StylePropertyMapReadOnly,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tfor (const property of style.keys()) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.get(property)!.toString()\n\n\t\tif (defaultStyles[property] === value) continue\n\t\tif (parentStyles[property] === value && isPropertyInherited(property)) continue\n\n\t\tstyles[property] = value\n\t}\n\n\treturn styles\n}\n\nfunction styleFromComputedStyle(\n\tstyle: CSSStyleDeclaration,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tfor (const property in style) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.getPropertyValue(property)\n\n\t\tif (defaultStyles[property] === value) continue\n\t\tif (parentStyles[property] === value && isPropertyInherited(property)) continue\n\n\t\tstyles[property] = value\n\t}\n\treturn styles\n}\n\nfunction formatCss(style: ReadonlyStyles) {\n\tlet cssText = ''\n\tfor (const [property, value] of Object.entries(style)) {\n\t\tcssText += `${property}: ${value};`\n\t}\n\treturn cssText\n}\n\n// when we're figuring out the default values for a tag, we need read them from a separate document\n// so they're not affected by the current document's styles\nlet defaultStyleFrame:\n\t| { iframe: HTMLIFrameElement; foreignObject: SVGForeignObjectElement; document: Document }\n\t| undefined\nconst defaultStylesByTagName: Record<string, ReadonlyStyles> = {}\nfunction getDefaultStyleFrame() {\n\tif (!defaultStyleFrame) {\n\t\tconst frame = document.createElement('iframe')\n\t\tframe.style.display = 'none'\n\t\tdocument.body.appendChild(frame)\n\t\tconst frameDocument = assertExists(frame.contentDocument, 'frame must have a document')\n\t\tconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n\t\tconst foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')\n\t\tsvg.appendChild(foreignObject)\n\t\tframeDocument.body.appendChild(svg)\n\t\tdefaultStyleFrame = { iframe: frame, foreignObject, document: frameDocument }\n\t}\n\treturn defaultStyleFrame\n}\n\nfunction destroyDefaultStyleFrame() {\n\tif (defaultStyleFrame) {\n\t\tdocument.body.removeChild(defaultStyleFrame.iframe)\n\t\tdefaultStyleFrame = undefined\n\t}\n}\n\nconst defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }\nfunction getDefaultStylesForTagName(tagName: string) {\n\tlet existing = defaultStylesByTagName[tagName]\n\tif (!existing) {\n\t\tconst { foreignObject, document } = getDefaultStyleFrame()\n\t\tconst element = document.createElement(tagName)\n\t\tforeignObject.appendChild(element)\n\t\texisting = element.computedStyleMap\n\t\t\t? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions)\n\t\t\t: styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions)\n\t\tforeignObject.removeChild(element)\n\t\tdefaultStylesByTagName[tagName] = existing\n\t}\n\treturn existing\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { assertExists, objectMapValues, uniqueId } from '@tldraw/utils'\nimport { FontEmbedder } from './FontEmbedder'\nimport {\n\telementStyle,\n\tgetComputedStyle,\n\tgetRenderedChildNodes,\n\tgetRenderedChildren,\n} from './domUtils'\nimport { resourceToDataUrl } from './fetchCache'\nimport {\n\tisPropertyCoveredByCurrentColor,\n\tisPropertyInherited,\n\tparseCssValueUrls,\n\tshouldIncludeCssProperty,\n} from './parseCss'\n\ntype Styles = { [K in string]?: string }\ntype ReadonlyStyles = { readonly [K in string]?: string }\nconst NO_STYLES = {} as const\n\ninterface ElementStyleInfo {\n\tself: Styles\n\tbefore: Styles | undefined\n\tafter: Styles | undefined\n}\n\nexport class StyleEmbedder {\n\tconstructor(private readonly root: Element) {}\n\tprivate readonly styles = new Map<Element, ElementStyleInfo>()\n\treadonly fonts = new FontEmbedder()\n\n\treadRootElementStyles(rootElement: Element) {\n\t\t// when reading a root, we always apply _all_ the styles, even if they match the defaults\n\t\tthis.readElementStyles(rootElement, {\n\t\t\tshouldRespectDefaults: false,\n\t\t\tshouldSkipInheritedParentStyles: false,\n\t\t})\n\n\t\tconst children = Array.from(getRenderedChildren(rootElement))\n\t\twhile (children.length) {\n\t\t\tconst child = children.pop()!\n\t\t\tchildren.push(...getRenderedChildren(child))\n\n\t\t\t// when reading children, we don't apply styles that match the defaults for that\n\t\t\t// element, or that would be inherited from the parent\n\t\t\tthis.readElementStyles(child, {\n\t\t\t\tshouldRespectDefaults: true,\n\t\t\t\tshouldSkipInheritedParentStyles: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tprivate readElementStyles(\n\t\telement: Element,\n\t\t{ shouldRespectDefaults = true, shouldSkipInheritedParentStyles = true }\n\t) {\n\t\tconst defaultStyles = shouldRespectDefaults\n\t\t\t? getDefaultStylesForTagName(element.tagName.toLowerCase())\n\t\t\t: NO_STYLES\n\n\t\tconst parentStyles = Object.assign({}, NO_STYLES) as Styles\n\t\tif (shouldSkipInheritedParentStyles) {\n\t\t\tlet el = element.parentElement\n\t\t\t// Keep going up the tree to find all the relevant styles\n\t\t\twhile (el) {\n\t\t\t\tconst currentStyles = this.styles.get(el)?.self\n\t\t\t\tfor (const style in currentStyles) {\n\t\t\t\t\tif (!parentStyles[style]) {\n\t\t\t\t\t\tparentStyles[style] = currentStyles[style]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tel = el.parentElement\n\t\t\t}\n\t\t}\n\n\t\tconst info: ElementStyleInfo = {\n\t\t\tself: styleFromElement(element, { defaultStyles, parentStyles }),\n\t\t\tbefore: styleFromPseudoElement(element, '::before'),\n\t\t\tafter: styleFromPseudoElement(element, '::after'),\n\t\t}\n\t\tthis.styles.set(element, info)\n\t}\n\n\tfetchResources() {\n\t\tconst promises: Promise<void>[] = []\n\n\t\tfor (const info of this.styles.values()) {\n\t\t\tfor (const styles of objectMapValues(info)) {\n\t\t\t\tif (!styles) continue\n\t\t\t\tfor (const [property, value] of Object.entries(styles)) {\n\t\t\t\t\tif (!value) continue\n\t\t\t\t\tif (property === 'font-family') {\n\t\t\t\t\t\tthis.fonts.onFontFamilyValue(value)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst urlMatches = parseCssValueUrls(value)\n\t\t\t\t\tif (urlMatches.length === 0) continue\n\n\t\t\t\t\tpromises.push(\n\t\t\t\t\t\t...urlMatches.map(async ({ url, original }) => {\n\t\t\t\t\t\t\tconst dataUrl = (await resourceToDataUrl(url)) ?? 'data:'\n\t\t\t\t\t\t\tstyles[property] = value.replace(original, `url(\"${dataUrl}\")`)\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Promise.all(promises)\n\t}\n\n\t// custom elements are tricky. if we serialize the dom as-is, the custom elements wont have\n\t// their shadow-dom contents serialized. after we've read all the styles, we need to unwrap the\n\t// contents of each custom elements shadow dom directly into the parent element itself.\n\tunwrapCustomElements() {\n\t\tconst visited = new Set<Node>()\n\n\t\tconst visit = (element: Element, clonedParent: Element | null) => {\n\t\t\tif (visited.has(element)) return\n\t\t\tvisited.add(element)\n\n\t\t\tconst shadowRoot = element.shadowRoot\n\n\t\t\tif (shadowRoot) {\n\t\t\t\tconst clonedCustomEl = document.createElement('div')\n\t\t\t\tthis.styles.set(clonedCustomEl, this.styles.get(element)!)\n\n\t\t\t\tclonedCustomEl.setAttribute('data-tl-custom-element', element.tagName)\n\t\t\t\t;(clonedParent ?? element.parentElement!).appendChild(clonedCustomEl)\n\n\t\t\t\tfor (const child of shadowRoot.childNodes) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedCustomEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedCustomEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.remove()\n\t\t\t} else if (clonedParent) {\n\t\t\t\tif (element.tagName.toLowerCase() === 'style') {\n\t\t\t\t\t// we don't clone style tags at that would break the style scoping. instead we\n\t\t\t\t\t// rely on the computed styles we've already read\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst clonedEl = element.cloneNode(false) as Element\n\t\t\t\tthis.styles.set(clonedEl, this.styles.get(element)!)\n\n\t\t\t\tclonedParent.appendChild(clonedEl)\n\n\t\t\t\tfor (const child of getRenderedChildNodes(element)) {\n\t\t\t\t\tif (child instanceof Element) {\n\t\t\t\t\t\tvisit(child, clonedEl)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclonedEl.appendChild(child.cloneNode(true))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const element of this.styles.keys()) {\n\t\t\tvisit(element, null)\n\t\t}\n\t}\n\n\tembedStyles(): string {\n\t\tlet css = ''\n\n\t\tfor (const [element, info] of this.styles) {\n\t\t\tif (info.after || info.before) {\n\t\t\t\tconst className = `pseudo-${uniqueId()}`\n\t\t\t\telement.classList.add(className)\n\n\t\t\t\tif (info.before) {\n\t\t\t\t\tcss += `.${className}::before {${formatCss(info.before)}}\\n`\n\t\t\t\t}\n\t\t\t\tif (info.after) {\n\t\t\t\t\tcss += `.${className}::after {${formatCss(info.after)}}\\n`\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst style = elementStyle(element)\n\t\t\tfor (const [property, value] of Object.entries(info.self)) {\n\t\t\t\tif (!value) continue\n\t\t\t\tstyle.setProperty(property, value)\n\t\t\t}\n\n\t\t\t// in HTML, font-kerning: auto is equivalent to font-kerning: normal. But in SVG, it's\n\t\t\t// none. We set it to normal here to match the HTML behavior, as otherwise this can\n\t\t\t// cause rendering differences.\n\t\t\tif (style.fontKerning === 'auto') {\n\t\t\t\tstyle.fontKerning = 'normal'\n\t\t\t}\n\t\t}\n\n\t\treturn css\n\t}\n\n\tasync getFontFaceCss() {\n\t\treturn await this.fonts.createCss()\n\t}\n\n\tdispose() {\n\t\tdestroyDefaultStyleFrame()\n\t}\n}\n\ninterface ReadStyleOpts {\n\tdefaultStyles: ReadonlyStyles\n\tparentStyles: ReadonlyStyles\n}\n\nfunction styleFromElement(element: Element, { defaultStyles, parentStyles }: ReadStyleOpts) {\n\t// `computedStyleMap` produces a more accurate representation of the styles, but it's not\n\t// supported in firefox at the time of writing. So we fall back to `getComputedStyle` if it's\n\t// not available.\n\tif (element.computedStyleMap) {\n\t\treturn styleFromComputedStyleMap(element.computedStyleMap(), { defaultStyles, parentStyles })\n\t}\n\treturn styleFromComputedStyle(getComputedStyle(element), { defaultStyles, parentStyles })\n}\n\nfunction styleFromPseudoElement(element: Element, pseudo: string) {\n\t// the equivalent of `computedStyleMap` for pseudo-elements isn't even fully specced out yet, so\n\t// for those we have to use `getComputedStyle` in all browsers.\n\tconst style = getComputedStyle(element, pseudo)\n\n\tconst content = style.getPropertyValue('content')\n\tif (content === '' || content === 'none') {\n\t\treturn undefined\n\t}\n\n\treturn styleFromComputedStyle(style, { defaultStyles: NO_STYLES, parentStyles: NO_STYLES })\n}\n\nfunction styleFromComputedStyleMap(\n\tstyle: StylePropertyMapReadOnly,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tfor (const property of style.keys()) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.get(property)!.toString()\n\n\t\tif (defaultStyles[property] === value) continue\n\t\tif (parentStyles[property] === value && isPropertyInherited(property)) continue\n\t\tif (isPropertyCoveredByCurrentColor(style.get('color')?.toString() || '', property, value))\n\t\t\tcontinue\n\n\t\tstyles[property] = value\n\t}\n\n\treturn styles\n}\n\nfunction styleFromComputedStyle(\n\tstyle: CSSStyleDeclaration,\n\t{ defaultStyles, parentStyles }: ReadStyleOpts\n) {\n\tconst styles: Record<string, string> = {}\n\tfor (const property in style) {\n\t\tif (!shouldIncludeCssProperty(property)) continue\n\n\t\tconst value = style.getPropertyValue(property)\n\n\t\tif (defaultStyles[property] === value) continue\n\t\tif (parentStyles[property] === value && isPropertyInherited(property)) continue\n\t\tif (isPropertyCoveredByCurrentColor(style.color, property, value)) continue\n\n\t\tstyles[property] = value\n\t}\n\treturn styles\n}\n\nfunction formatCss(style: ReadonlyStyles) {\n\tlet cssText = ''\n\tfor (const [property, value] of Object.entries(style)) {\n\t\tcssText += `${property}: ${value};`\n\t}\n\treturn cssText\n}\n\n// when we're figuring out the default values for a tag, we need read them from a separate document\n// so they're not affected by the current document's styles\nlet defaultStyleFrame:\n\t| { iframe: HTMLIFrameElement; foreignObject: SVGForeignObjectElement; document: Document }\n\t| undefined\nconst defaultStylesByTagName: Record<string, ReadonlyStyles> = {}\nfunction getDefaultStyleFrame() {\n\tif (!defaultStyleFrame) {\n\t\tconst frame = document.createElement('iframe')\n\t\tframe.style.display = 'none'\n\t\tdocument.body.appendChild(frame)\n\t\tconst frameDocument = assertExists(frame.contentDocument, 'frame must have a document')\n\t\tconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n\t\tconst foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')\n\t\tsvg.appendChild(foreignObject)\n\t\tframeDocument.body.appendChild(svg)\n\t\tdefaultStyleFrame = { iframe: frame, foreignObject, document: frameDocument }\n\t}\n\treturn defaultStyleFrame\n}\n\nfunction destroyDefaultStyleFrame() {\n\tif (defaultStyleFrame) {\n\t\tdocument.body.removeChild(defaultStyleFrame.iframe)\n\t\tdefaultStyleFrame = undefined\n\t}\n}\n\nconst defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }\nfunction getDefaultStylesForTagName(tagName: string) {\n\tlet existing = defaultStylesByTagName[tagName]\n\tif (!existing) {\n\t\tconst { foreignObject, document } = getDefaultStyleFrame()\n\t\tconst element = document.createElement(tagName)\n\t\tforeignObject.appendChild(element)\n\t\texisting = element.computedStyleMap\n\t\t\t? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions)\n\t\t\t: styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions)\n\t\tforeignObject.removeChild(element)\n\t\tdefaultStylesByTagName[tagName] = existing\n\t}\n\treturn existing\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["document"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/exports/exportToSvg.tsx"],
4
- "sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport { Editor } from '../editor/Editor'\nimport { TLSvgExportOptions } from '../editor/types/misc-types'\nimport { SVG_EXPORT_CLASSNAME } from './FontEmbedder'\nimport { StyleEmbedder } from './StyleEmbedder'\nimport { embedMedia } from './embedMedia'\nimport { getSvgJsx } from './getSvgJsx'\n\nlet idCounter = 1\n\nexport async function exportToSvg(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts: TLSvgExportOptions = {}\n) {\n\t// when rendering to SVG, we start by creating a JSX representation of the SVG that we can\n\t// render with react. Hopefully elements will have a `toSvg` method that renders them to SVG,\n\t// but if they don't we'll render their normal HTML content into an svg <foreignObject> element.\n\tconst result = getSvgJsx(editor, shapeIds, opts)\n\tif (!result) return undefined\n\n\t// we need to render that SVG into a real DOM element that's actually laid out in the document.\n\t// without this CSS and layout aren't computed correctly, which we need to make sure any\n\t// <foreignObject> elements have their styles and content inlined correctly.\n\tconst container = editor.getContainer()\n\tconst renderTarget = document.createElement('div')\n\trenderTarget.className = SVG_EXPORT_CLASSNAME\n\t// we hide the element visually, but we don't want it to be focusable or interactive in any way either\n\trenderTarget.inert = true\n\trenderTarget.tabIndex = -1\n\tObject.assign(renderTarget.style, {\n\t\tposition: 'absolute',\n\t\ttop: '0px',\n\t\tleft: '0px',\n\t\twidth: result.width + 'px',\n\t\theight: result.height + 'px',\n\t\tpointerEvents: 'none',\n\t\topacity: 0,\n\t})\n\t// we have to add the element to the document as otherwise styles won't be computed correctly.\n\tcontainer.appendChild(renderTarget)\n\n\t// create a react root...\n\tconst root = createRoot(renderTarget, { identifierPrefix: `export_${idCounter++}_` })\n\ttry {\n\t\t// ...wait for a tick so we know we're not in e.g. a react lifecycle method...\n\t\tawait Promise.resolve()\n\n\t\t// ...and render the SVG into it.\n\t\tflushSync(() => {\n\t\t\troot.render(result.jsx)\n\t\t})\n\n\t\t// Some operations take a while - for example, waiting for an asset to load in. We give\n\t\t// shape authors a way to delay snap-shotting the export until they're ready.\n\t\tawait result.exportDelay.resolve()\n\n\t\t// Extract the rendered SVG element from the react root\n\t\tconst svg = renderTarget.firstElementChild\n\t\tassert(svg instanceof SVGSVGElement, 'Expected an SVG element')\n\n\t\t// And apply any changes to <foreignObject> elements that we need to make. Whilst we're in\n\t\t// the document, these elements work exactly as we'd expect from other dom elements - they\n\t\t// can load external resources, and any stylesheets in the document apply to them as we\n\t\t// would expect them to. But when we pull the SVG into its own file or draw it to a canvas\n\t\t// though, it has to be completely self-contained. We embed any external resources, and\n\t\t// apply any styles directly to the elements themselves.\n\t\tawait applyChangesToForeignObjects(svg)\n\n\t\treturn { svg, width: result.width, height: result.height }\n\t} finally {\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tsetTimeout(() => {\n\t\t\t// we wait for a cycle of the event loop to allow the svg to be cloned etc. before\n\t\t\t// unmounting\n\t\t\troot.unmount()\n\t\t\tcontainer.removeChild(renderTarget)\n\t\t}, 0)\n\t}\n}\n\nasync function applyChangesToForeignObjects(svg: SVGSVGElement) {\n\t// If any shapes have their own <foreignObject> elements, we don't want to mess with them. Our\n\t// ones that we need to embed will have a class of `tl-export-embed-styles`.\n\tconst foreignObjectChildren = [\n\t\t...svg.querySelectorAll('foreignObject.tl-export-embed-styles > *'),\n\t]\n\tif (!foreignObjectChildren.length) return\n\n\t// StyleEmbedder embeds any CSS - including resources like fonts and images.\n\tconst styleEmbedder = new StyleEmbedder(svg)\n\n\ttry {\n\t\t// begin traversing stylesheets to find @font-face declarations we might need to embed\n\t\tstyleEmbedder.fonts.startFindingCurrentDocumentFontFaces()\n\n\t\t// embed any media elements in the foreignObject children. images will get converted to data\n\t\t// urls, and things like videos will be converted to images.\n\t\tawait Promise.all(foreignObjectChildren.map((el) => embedMedia(el as HTMLElement)))\n\n\t\t// read the computed styles of every element (+ it's children & pseudo-elements) in the\n\t\t// document. we do this in a single pass before we start embedding any CSS stuff to avoid\n\t\t// constantly forcing the browser to recompute styles & layout.\n\t\tfor (const el of foreignObjectChildren) {\n\t\t\tstyleEmbedder.readRootElementStyles(el as HTMLElement)\n\t\t}\n\n\t\t// fetch any resources that we need to embed in the CSS, like background images.\n\t\tawait styleEmbedder.fetchResources()\n\t\tconst fontCss = await styleEmbedder.getFontFaceCss()\n\n\t\t// custom elements that make use of the shadow dom won't be serialized correctly by default:\n\t\t// the contents of the shadow dom will be ignored. once we've read the styles from the\n\t\t// document, we go through and replace any custom elements with plain `<div>`s. as we do so,\n\t\t// we traverse the shadow dom and clone it into the new plain div. any scoped stylesheets\n\t\t// are removed, as we've already read all the computed styles above.\n\t\tstyleEmbedder.unwrapCustomElements()\n\n\t\t// apply the computed styles (with their embedded resources) directly to the elements with\n\t\t// their `style` attribute. Anything that can't be done this way (pseudo-elements) will be\n\t\t// returned as a string of CSS.\n\t\tconst pseudoCss = styleEmbedder.embedStyles()\n\n\t\t// add the CSS to the SVG\n\t\tif (fontCss || pseudoCss) {\n\t\t\tconst style = document.createElementNS('http://www.w3.org/2000/svg', 'style')\n\t\t\tstyle.textContent = `${fontCss}\\n${pseudoCss}`\n\t\t\tsvg.prepend(style)\n\t\t}\n\t} finally {\n\t\tstyleEmbedder.dispose()\n\t}\n}\n"],
4
+ "sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport { Editor } from '../editor/Editor'\nimport { TLSvgExportOptions } from '../editor/types/misc-types'\nimport { SVG_EXPORT_CLASSNAME } from './FontEmbedder'\nimport { StyleEmbedder } from './StyleEmbedder'\nimport { embedMedia } from './embedMedia'\nimport { getSvgJsx } from './getSvgJsx'\n\nlet idCounter = 1\n\nexport async function exportToSvg(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts: TLSvgExportOptions = {}\n) {\n\t// when rendering to SVG, we start by creating a JSX representation of the SVG that we can\n\t// render with react. Hopefully elements will have a `toSvg` method that renders them to SVG,\n\t// but if they don't we'll render their normal HTML content into an svg <foreignObject> element.\n\tconst result = getSvgJsx(editor, shapeIds, opts)\n\tif (!result) return undefined\n\n\t// we need to render that SVG into a real DOM element that's actually laid out in the document.\n\t// without this CSS and layout aren't computed correctly, which we need to make sure any\n\t// <foreignObject> elements have their styles and content inlined correctly.\n\tconst container = editor.getContainer()\n\tconst renderTarget = document.createElement('div')\n\trenderTarget.className = SVG_EXPORT_CLASSNAME\n\t// we hide the element visually, but we don't want it to be focusable or interactive in any way either\n\trenderTarget.inert = true\n\trenderTarget.tabIndex = -1\n\tObject.assign(renderTarget.style, {\n\t\tposition: 'absolute',\n\t\ttop: '0px',\n\t\tleft: '0px',\n\t\twidth: result.width + 'px',\n\t\theight: result.height + 'px',\n\t\tpointerEvents: 'none',\n\t\topacity: 0,\n\t})\n\t// we have to add the element to the document as otherwise styles won't be computed correctly.\n\tcontainer.appendChild(renderTarget)\n\n\t// create a react root...\n\tconst root = createRoot(renderTarget, { identifierPrefix: `export_${idCounter++}_` })\n\ttry {\n\t\t// ...wait for a tick so we know we're not in e.g. a react lifecycle method...\n\t\tawait Promise.resolve()\n\n\t\t// ...and render the SVG into it.\n\t\tflushSync(() => {\n\t\t\troot.render(result.jsx)\n\t\t})\n\n\t\t// Some operations take a while - for example, waiting for an asset to load in. We give\n\t\t// shape authors a way to delay snap-shotting the export until they're ready.\n\t\tawait result.exportDelay.resolve()\n\n\t\t// Extract the rendered SVG element from the react root\n\t\tconst svg = renderTarget.firstElementChild\n\t\tassert(svg instanceof SVGSVGElement, 'Expected an SVG element')\n\n\t\t// And apply any changes to <foreignObject> elements that we need to make. while we're in\n\t\t// the document, these elements work exactly as we'd expect from other dom elements - they\n\t\t// can load external resources, and any stylesheets in the document apply to them as we\n\t\t// would expect them to. But when we pull the SVG into its own file or draw it to a canvas\n\t\t// though, it has to be completely self-contained. We embed any external resources, and\n\t\t// apply any styles directly to the elements themselves.\n\t\tawait applyChangesToForeignObjects(svg)\n\n\t\treturn { svg, width: result.width, height: result.height }\n\t} finally {\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tsetTimeout(() => {\n\t\t\t// we wait for a cycle of the event loop to allow the svg to be cloned etc. before\n\t\t\t// unmounting\n\t\t\troot.unmount()\n\t\t\tcontainer.removeChild(renderTarget)\n\t\t}, 0)\n\t}\n}\n\nasync function applyChangesToForeignObjects(svg: SVGSVGElement) {\n\t// If any shapes have their own <foreignObject> elements, we don't want to mess with them. Our\n\t// ones that we need to embed will have a class of `tl-export-embed-styles`.\n\tconst foreignObjectChildren = [\n\t\t...svg.querySelectorAll('foreignObject.tl-export-embed-styles > *'),\n\t]\n\tif (!foreignObjectChildren.length) return\n\n\t// StyleEmbedder embeds any CSS - including resources like fonts and images.\n\tconst styleEmbedder = new StyleEmbedder(svg)\n\n\ttry {\n\t\t// begin traversing stylesheets to find @font-face declarations we might need to embed\n\t\tstyleEmbedder.fonts.startFindingCurrentDocumentFontFaces()\n\n\t\t// embed any media elements in the foreignObject children. images will get converted to data\n\t\t// urls, and things like videos will be converted to images.\n\t\tawait Promise.all(foreignObjectChildren.map((el) => embedMedia(el as HTMLElement)))\n\n\t\t// read the computed styles of every element (+ it's children & pseudo-elements) in the\n\t\t// document. we do this in a single pass before we start embedding any CSS stuff to avoid\n\t\t// constantly forcing the browser to recompute styles & layout.\n\t\tfor (const el of foreignObjectChildren) {\n\t\t\tstyleEmbedder.readRootElementStyles(el as HTMLElement)\n\t\t}\n\n\t\t// fetch any resources that we need to embed in the CSS, like background images.\n\t\tawait styleEmbedder.fetchResources()\n\t\tconst fontCss = await styleEmbedder.getFontFaceCss()\n\n\t\t// custom elements that make use of the shadow dom won't be serialized correctly by default:\n\t\t// the contents of the shadow dom will be ignored. once we've read the styles from the\n\t\t// document, we go through and replace any custom elements with plain `<div>`s. as we do so,\n\t\t// we traverse the shadow dom and clone it into the new plain div. any scoped stylesheets\n\t\t// are removed, as we've already read all the computed styles above.\n\t\tstyleEmbedder.unwrapCustomElements()\n\n\t\t// apply the computed styles (with their embedded resources) directly to the elements with\n\t\t// their `style` attribute. Anything that can't be done this way (pseudo-elements) will be\n\t\t// returned as a string of CSS.\n\t\tconst pseudoCss = styleEmbedder.embedStyles()\n\n\t\t// add the CSS to the SVG\n\t\tif (fontCss || pseudoCss) {\n\t\t\tconst style = document.createElementNS('http://www.w3.org/2000/svg', 'style')\n\t\t\tstyle.textContent = `${fontCss}\\n${pseudoCss}`\n\t\t\tsvg.prepend(style)\n\t\t}\n\t} finally {\n\t\tstyleEmbedder.dispose()\n\t}\n}\n"],
5
5
  "mappings": "AACA,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAG3B,SAAS,4BAA4B;AACrC,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAE1B,IAAI,YAAY;AAEhB,eAAsB,YACrB,QACA,UACA,OAA2B,CAAC,GAC3B;AAID,QAAM,SAAS,UAAU,QAAQ,UAAU,IAAI;AAC/C,MAAI,CAAC,OAAQ,QAAO;AAKpB,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,eAAe,SAAS,cAAc,KAAK;AACjD,eAAa,YAAY;AAEzB,eAAa,QAAQ;AACrB,eAAa,WAAW;AACxB,SAAO,OAAO,aAAa,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO,OAAO,QAAQ;AAAA,IACtB,QAAQ,OAAO,SAAS;AAAA,IACxB,eAAe;AAAA,IACf,SAAS;AAAA,EACV,CAAC;AAED,YAAU,YAAY,YAAY;AAGlC,QAAM,OAAO,WAAW,cAAc,EAAE,kBAAkB,UAAU,WAAW,IAAI,CAAC;AACpF,MAAI;AAEH,UAAM,QAAQ,QAAQ;AAGtB,cAAU,MAAM;AACf,WAAK,OAAO,OAAO,GAAG;AAAA,IACvB,CAAC;AAID,UAAM,OAAO,YAAY,QAAQ;AAGjC,UAAM,MAAM,aAAa;AACzB,WAAO,eAAe,eAAe,yBAAyB;AAQ9D,UAAM,6BAA6B,GAAG;AAEtC,WAAO,EAAE,KAAK,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAAA,EAC1D,UAAE;AAED,eAAW,MAAM;AAGhB,WAAK,QAAQ;AACb,gBAAU,YAAY,YAAY;AAAA,IACnC,GAAG,CAAC;AAAA,EACL;AACD;AAEA,eAAe,6BAA6B,KAAoB;AAG/D,QAAM,wBAAwB;AAAA,IAC7B,GAAG,IAAI,iBAAiB,0CAA0C;AAAA,EACnE;AACA,MAAI,CAAC,sBAAsB,OAAQ;AAGnC,QAAM,gBAAgB,IAAI,cAAc,GAAG;AAE3C,MAAI;AAEH,kBAAc,MAAM,qCAAqC;AAIzD,UAAM,QAAQ,IAAI,sBAAsB,IAAI,CAAC,OAAO,WAAW,EAAiB,CAAC,CAAC;AAKlF,eAAW,MAAM,uBAAuB;AACvC,oBAAc,sBAAsB,EAAiB;AAAA,IACtD;AAGA,UAAM,cAAc,eAAe;AACnC,UAAM,UAAU,MAAM,cAAc,eAAe;AAOnD,kBAAc,qBAAqB;AAKnC,UAAM,YAAY,cAAc,YAAY;AAG5C,QAAI,WAAW,WAAW;AACzB,YAAM,QAAQ,SAAS,gBAAgB,8BAA8B,OAAO;AAC5E,YAAM,cAAc,GAAG,OAAO;AAAA,EAAK,SAAS;AAC5C,UAAI,QAAQ,KAAK;AAAA,IAClB;AAAA,EACD,UAAE;AACD,kBAAc,QAAQ;AAAA,EACvB;AACD;",
6
6
  "names": []
7
7
  }
@@ -266,7 +266,7 @@ function SvgExport({
266
266
  key: uniqueId(),
267
267
  getElement: async () => {
268
268
  const declaration = await editor.fonts.toEmbeddedCssDeclaration(font);
269
- return /* @__PURE__ */ jsx("style", { children: declaration });
269
+ return /* @__PURE__ */ jsx("style", { nonce: editor.options.nonce, children: declaration });
270
270
  }
271
271
  });
272
272
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/exports/getSvgJsx.tsx"],
4
- "sourcesContent": ["import { useAtom, useValue } from '@tldraw/state-react'\nimport {\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLShape,\n\tTLShapeId,\n\tgetDefaultColorTheme,\n} from '@tldraw/tlschema'\nimport { hasOwnProperty, promiseWithResolve, uniqueId } from '@tldraw/utils'\nimport {\n\tComponentType,\n\tFragment,\n\tReactElement,\n\tReactNode,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n} from 'react'\nimport { flushSync } from 'react-dom'\nimport { ErrorBoundary } from '../components/ErrorBoundary'\nimport { InnerShape, InnerShapeBackground } from '../components/Shape'\nimport { Editor, TLRenderingShape } from '../editor/Editor'\nimport { TLFontFace } from '../editor/managers/FontManager'\nimport { ShapeUtil } from '../editor/shapes/ShapeUtil'\nimport {\n\tSvgExportContext,\n\tSvgExportContextProvider,\n\tSvgExportDef,\n} from '../editor/types/SvgExportContext'\nimport { TLImageExportOptions } from '../editor/types/misc-types'\nimport { useEditor } from '../hooks/useEditor'\nimport { useEvent } from '../hooks/useEvent'\nimport { suffixSafeId, useUniqueSafeId } from '../hooks/useSafeId'\nimport { Box } from '../primitives/Box'\nimport { Mat } from '../primitives/Mat'\nimport { ExportDelay } from './ExportDelay'\n\nexport function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions = {}) {\n\tif (!window.document) throw Error('No document')\n\n\tconst {\n\t\tscale = 1,\n\t\t// should we include the background in the export? or is it transparent?\n\t\tbackground = editor.getInstanceState().exportBackground,\n\t\tpadding = editor.options.defaultSvgPadding,\n\t\tpreserveAspectRatio,\n\t} = opts\n\n\tconst isDarkMode = opts.darkMode ?? editor.user.getIsDarkMode()\n\n\t// ---Figure out which shapes we need to include\n\tconst shapeIdsToInclude = editor.getShapeAndDescendantIds(ids)\n\tconst renderingShapes = editor\n\t\t.getUnorderedRenderingShapes(false)\n\t\t.filter(({ id }) => shapeIdsToInclude.has(id))\n\n\t// --- Common bounding box of all shapes\n\tlet bbox: null | Box = null\n\tif (opts.bounds) {\n\t\tbbox = opts.bounds\n\t} else {\n\t\tfor (const { id } of renderingShapes) {\n\t\t\tconst maskedPageBounds = editor.getShapeMaskedPageBounds(id)\n\t\t\tif (!maskedPageBounds) continue\n\t\t\tif (bbox) {\n\t\t\t\tbbox.union(maskedPageBounds)\n\t\t\t} else {\n\t\t\t\tbbox = maskedPageBounds.clone()\n\t\t\t}\n\t\t}\n\t}\n\n\t// no unmasked shapes to export\n\tif (!bbox) return\n\n\tconst singleFrameShapeId =\n\t\tids.length === 1 && editor.isShapeOfType<TLFrameShape>(editor.getShape(ids[0])!, 'frame')\n\t\t\t? ids[0]\n\t\t\t: null\n\tif (!singleFrameShapeId) {\n\t\t// Expand by an extra 32 pixels\n\t\tbbox.expandBy(padding)\n\t}\n\n\t// We want the svg image to be BIGGER THAN USUAL to account for image quality\n\tconst w = bbox.width * scale\n\tconst h = bbox.height * scale\n\n\ttry {\n\t\tdocument.body.focus?.() // weird but necessary\n\t} catch {\n\t\t// not implemented\n\t}\n\n\tconst exportDelay = new ExportDelay(editor.options.maxExportDelayMs)\n\n\tconst initialEffectPromise = promiseWithResolve<void>()\n\texportDelay.waitUntil(initialEffectPromise)\n\n\tconst svg = (\n\t\t<SvgExport\n\t\t\teditor={editor}\n\t\t\tpreserveAspectRatio={preserveAspectRatio}\n\t\t\tscale={scale}\n\t\t\tpixelRatio={opts.pixelRatio ?? null}\n\t\t\tbbox={bbox}\n\t\t\tbackground={background}\n\t\t\tsingleFrameShapeId={singleFrameShapeId}\n\t\t\tisDarkMode={isDarkMode}\n\t\t\trenderingShapes={renderingShapes}\n\t\t\tonMount={initialEffectPromise.resolve}\n\t\t\twaitUntil={exportDelay.waitUntil}\n\t\t>\n\t\t\t{}\n\t\t</SvgExport>\n\t)\n\n\treturn { jsx: svg, width: w, height: h, exportDelay }\n}\n\nfunction SvgExport({\n\teditor,\n\tpreserveAspectRatio,\n\tscale,\n\tpixelRatio,\n\tbbox,\n\tbackground,\n\tsingleFrameShapeId,\n\tisDarkMode,\n\trenderingShapes,\n\tonMount,\n\twaitUntil,\n}: {\n\teditor: Editor\n\tpreserveAspectRatio?: string\n\tscale: number\n\tpixelRatio: number | null\n\tbbox: Box\n\tbackground: boolean\n\tsingleFrameShapeId: TLShapeId | null\n\tisDarkMode: boolean\n\trenderingShapes: TLRenderingShape[]\n\tonMount(): void\n\twaitUntil(promise: Promise<void>): void\n}) {\n\tconst masksId = useUniqueSafeId()\n\tconst theme = getDefaultColorTheme({ isDarkMode })\n\n\tconst stateAtom = useAtom<{\n\t\tdefsById: Record<\n\t\t\tstring,\n\t\t\t{ pending: false; element: ReactNode } | { pending: true; element: Promise<ReactNode> }\n\t\t>\n\t\tshapeElements: ReactElement[] | null\n\t}>('export state', { defsById: {}, shapeElements: null })\n\tconst { defsById, shapeElements } = useValue(stateAtom)\n\n\tconst addExportDef = useEvent((def: SvgExportDef) => {\n\t\tstateAtom.update((state) => {\n\t\t\tif (hasOwnProperty(state.defsById, def.key)) return state\n\n\t\t\tconst promise = Promise.resolve(def.getElement())\n\t\t\twaitUntil(\n\t\t\t\tpromise.then((result) => {\n\t\t\t\t\tstateAtom.update((state) => ({\n\t\t\t\t\t\t...state,\n\t\t\t\t\t\tdefsById: { ...state.defsById, [def.key]: { pending: false, element: result } },\n\t\t\t\t\t}))\n\t\t\t\t})\n\t\t\t)\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tdefsById: { ...state.defsById, [def.key]: { pending: true, element: promise } },\n\t\t\t}\n\t\t})\n\t})\n\n\tconst exportContext = useMemo(\n\t\t(): SvgExportContext => ({\n\t\t\tisDarkMode,\n\t\t\twaitUntil,\n\t\t\taddExportDef,\n\t\t\tscale,\n\t\t\tpixelRatio,\n\t\t\tasync resolveAssetUrl(assetId, width) {\n\t\t\t\tconst asset = editor.getAsset(assetId)\n\t\t\t\tif (!asset || (asset.type !== 'image' && asset.type !== 'video')) return null\n\n\t\t\t\treturn await editor.resolveAssetUrl(assetId, {\n\t\t\t\t\tscreenScale: scale * (width / asset.props.w),\n\t\t\t\t\tshouldResolveToOriginal: pixelRatio === null,\n\t\t\t\t\tdpr: pixelRatio ?? undefined,\n\t\t\t\t})\n\t\t\t},\n\t\t}),\n\t\t[isDarkMode, waitUntil, addExportDef, scale, pixelRatio, editor]\n\t)\n\n\tconst didRenderRef = useRef(false)\n\tuseLayoutEffect(() => {\n\t\tif (didRenderRef.current) {\n\t\t\tthrow new Error('SvgExport should only render once - do not use with react strict mode')\n\t\t}\n\t\tdidRenderRef.current = true\n\t\t;(async () => {\n\t\t\tconst shapeDefs: Record<string, { pending: false; element: ReactElement }> = {}\n\n\t\t\t// Then render everything. The shapes with assets should all hit the cache\n\t\t\tconst unorderedShapeElementPromises = renderingShapes.map(\n\t\t\t\tasync ({ id, opacity, index, backgroundIndex }) => {\n\t\t\t\t\t// Don't render the frame if we're only exporting a single frame and it's children\n\t\t\t\t\tif (id === singleFrameShapeId) return []\n\n\t\t\t\t\tconst shape = editor.getShape(id)!\n\n\t\t\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) return []\n\n\t\t\t\t\tconst elements = []\n\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\n\t\t\t\t\tif (util.toSvg || util.toBackgroundSvg) {\n\t\t\t\t\t\t// If the shape has any sort of custom svg export, let's use that.\n\t\t\t\t\t\tconst [toSvgResult, toBackgroundSvgResult] = await Promise.all([\n\t\t\t\t\t\t\tutil.toSvg?.(shape, exportContext),\n\t\t\t\t\t\t\tutil.toBackgroundSvg?.(shape, exportContext),\n\t\t\t\t\t\t])\n\n\t\t\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\t\t\t\tlet pageTransformString = pageTransform!.toCssString()\n\t\t\t\t\t\tlet scale = 1\n\t\t\t\t\t\tif ('scale' in shape.props) {\n\t\t\t\t\t\t\tif (shape.props.scale !== 1) {\n\t\t\t\t\t\t\t\tscale = shape.props.scale\n\t\t\t\t\t\t\t\tpageTransformString = `${pageTransformString} scale(${shape.props.scale}, ${shape.props.scale})`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Create svg mask if shape has a frame as parent\n\t\t\t\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\t\t\t\tconst shapeMask = pageMask\n\t\t\t\t\t\t\t? Mat.From(Mat.Inverse(pageTransform)).applyToPoints(pageMask)\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tconst shapeMaskId = suffixSafeId(masksId, shape.id)\n\t\t\t\t\t\tif (shapeMask) {\n\t\t\t\t\t\t\t// Create a clip path and add it to defs\n\t\t\t\t\t\t\tshapeDefs[shapeMaskId] = {\n\t\t\t\t\t\t\t\tpending: false,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<clipPath id={shapeMaskId}>\n\t\t\t\t\t\t\t\t\t\t{/* Create a polyline mask that does the clipping */}\n\t\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\t\td={`M${shapeMask.map(({ x, y }) => `${x / scale},${y / scale}`).join('L')}Z`}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</clipPath>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (toSvgResult) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: index,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\t\t\tkey={`fg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\ttransform={pageTransformString}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t\tclipPath={pageMask ? `url(#${shapeMaskId})` : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{toSvgResult}\n\t\t\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (toBackgroundSvgResult) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: backgroundIndex,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\t\t\tkey={`bg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\ttransform={pageTransformString}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t\tclipPath={pageMask ? `url(#${shapeMaskId})` : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{toBackgroundSvgResult}\n\t\t\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If the shape doesn't have a custom svg export, we'll use its normal HTML\n\t\t\t\t\t\t// renderer in a foreignObject.\n\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\tzIndex: index,\n\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t<ForeignObjectShape\n\t\t\t\t\t\t\t\t\tkey={`fg_${shape.id}`}\n\t\t\t\t\t\t\t\t\tshape={shape}\n\t\t\t\t\t\t\t\t\tutil={util}\n\t\t\t\t\t\t\t\t\tcomponent={InnerShape}\n\t\t\t\t\t\t\t\t\tclassName=\"tl-shape\"\n\t\t\t\t\t\t\t\t\tbbox={bbox}\n\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (util.backgroundComponent) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: backgroundIndex,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<ForeignObjectShape\n\t\t\t\t\t\t\t\t\t\tkey={`bg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\tshape={shape}\n\t\t\t\t\t\t\t\t\t\tutil={util}\n\t\t\t\t\t\t\t\t\t\tcomponent={InnerShapeBackground}\n\t\t\t\t\t\t\t\t\t\tclassName=\"tl-shape tl-shape-background\"\n\t\t\t\t\t\t\t\t\t\tbbox={bbox}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn elements\n\t\t\t\t}\n\t\t\t)\n\n\t\t\tconst unorderedShapeElements = (await Promise.all(unorderedShapeElementPromises)).flat()\n\n\t\t\tflushSync(() => {\n\t\t\t\tstateAtom.update((state) => ({\n\t\t\t\t\t...state,\n\t\t\t\t\tshapeElements: unorderedShapeElements\n\t\t\t\t\t\t.sort((a, b) => a.zIndex - b.zIndex)\n\t\t\t\t\t\t.map(({ element }) => element),\n\t\t\t\t\tdefsById: { ...state.defsById, ...shapeDefs },\n\t\t\t\t}))\n\t\t\t})\n\t\t})()\n\t}, [bbox, editor, exportContext, masksId, renderingShapes, singleFrameShapeId, stateAtom])\n\n\tuseEffect(() => {\n\t\tconst fontsInUse = new Set<TLFontFace>()\n\t\tfor (const { id } of renderingShapes) {\n\t\t\tfor (const font of editor.fonts.getShapeFontFaces(id)) {\n\t\t\t\tfontsInUse.add(font)\n\t\t\t}\n\t\t}\n\n\t\tfor (const font of fontsInUse) {\n\t\t\taddExportDef({\n\t\t\t\tkey: uniqueId(),\n\t\t\t\tgetElement: async () => {\n\t\t\t\t\tconst declaration = await editor.fonts.toEmbeddedCssDeclaration(font)\n\t\t\t\t\treturn <style>{declaration}</style>\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}, [editor, renderingShapes, addExportDef])\n\n\tuseEffect(() => {\n\t\tif (shapeElements === null) return\n\t\tonMount()\n\t}, [onMount, shapeElements])\n\n\treturn (\n\t\t<SvgExportContextProvider editor={editor} context={exportContext}>\n\t\t\t<svg\n\t\t\t\tpreserveAspectRatio={preserveAspectRatio}\n\t\t\t\tdirection=\"ltr\"\n\t\t\t\twidth={bbox.width * scale}\n\t\t\t\theight={bbox.height * scale}\n\t\t\t\tviewBox={`${bbox.minX} ${bbox.minY} ${bbox.width} ${bbox.height}`}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: background\n\t\t\t\t\t\t? singleFrameShapeId\n\t\t\t\t\t\t\t? theme.solid\n\t\t\t\t\t\t\t: theme.background\n\t\t\t\t\t\t: 'transparent',\n\t\t\t\t}}\n\t\t\t\tdata-color-mode={isDarkMode ? 'dark' : 'light'}\n\t\t\t\tclassName={`tl-container tl-theme__force-sRGB ${isDarkMode ? 'tl-theme__dark' : 'tl-theme__light'}`}\n\t\t\t>\n\t\t\t\t<defs>\n\t\t\t\t\t{Object.entries(defsById).map(([key, def]) =>\n\t\t\t\t\t\tdef.pending ? null : <Fragment key={key}>{def.element}</Fragment>\n\t\t\t\t\t)}\n\t\t\t\t</defs>\n\t\t\t\t{shapeElements}\n\t\t\t</svg>\n\t\t</SvgExportContextProvider>\n\t)\n}\n\nfunction ForeignObjectShape({\n\tshape,\n\tutil,\n\tclassName,\n\tcomponent: Component,\n\tbbox,\n\topacity,\n}: {\n\tshape: TLShape\n\tutil: ShapeUtil\n\tclassName?: string\n\tcomponent: ComponentType<{ shape: TLShape; util: ShapeUtil }>\n\tbbox: Box\n\topacity: number\n}) {\n\tconst editor = useEditor()\n\n\tconst transform = Mat.Translate(-bbox.minX, -bbox.minY).multiply(\n\t\teditor.getShapePageTransform(shape.id)!\n\t)\n\n\tconst bounds = editor.getShapeGeometry(shape.id).bounds\n\tconst width = Math.max(bounds.width, 1)\n\tconst height = Math.max(bounds.height, 1)\n\n\treturn (\n\t\t<ErrorBoundary fallback={() => null}>\n\t\t\t<foreignObject\n\t\t\t\tx={bbox.minX}\n\t\t\t\ty={bbox.minY}\n\t\t\t\twidth={bbox.w}\n\t\t\t\theight={bbox.h}\n\t\t\t\tclassName=\"tl-shape-foreign-object tl-export-embed-styles\"\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tdata-shape-type={shape.type}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tclipPath: editor.getShapeClipPath(shape.id),\n\t\t\t\t\t\ttransform: transform.toCssString(),\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\topacity,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<Component shape={shape} util={util} />\n\t\t\t\t</div>\n\t\t\t</foreignObject>\n\t\t</ErrorBoundary>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useAtom, useValue } from '@tldraw/state-react'\nimport {\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLShape,\n\tTLShapeId,\n\tgetDefaultColorTheme,\n} from '@tldraw/tlschema'\nimport { hasOwnProperty, promiseWithResolve, uniqueId } from '@tldraw/utils'\nimport {\n\tComponentType,\n\tFragment,\n\tReactElement,\n\tReactNode,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n} from 'react'\nimport { flushSync } from 'react-dom'\nimport { ErrorBoundary } from '../components/ErrorBoundary'\nimport { InnerShape, InnerShapeBackground } from '../components/Shape'\nimport { Editor, TLRenderingShape } from '../editor/Editor'\nimport { TLFontFace } from '../editor/managers/FontManager'\nimport { ShapeUtil } from '../editor/shapes/ShapeUtil'\nimport {\n\tSvgExportContext,\n\tSvgExportContextProvider,\n\tSvgExportDef,\n} from '../editor/types/SvgExportContext'\nimport { TLImageExportOptions } from '../editor/types/misc-types'\nimport { useEditor } from '../hooks/useEditor'\nimport { useEvent } from '../hooks/useEvent'\nimport { suffixSafeId, useUniqueSafeId } from '../hooks/useSafeId'\nimport { Box } from '../primitives/Box'\nimport { Mat } from '../primitives/Mat'\nimport { ExportDelay } from './ExportDelay'\n\nexport function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions = {}) {\n\tif (!window.document) throw Error('No document')\n\n\tconst {\n\t\tscale = 1,\n\t\t// should we include the background in the export? or is it transparent?\n\t\tbackground = editor.getInstanceState().exportBackground,\n\t\tpadding = editor.options.defaultSvgPadding,\n\t\tpreserveAspectRatio,\n\t} = opts\n\n\tconst isDarkMode = opts.darkMode ?? editor.user.getIsDarkMode()\n\n\t// ---Figure out which shapes we need to include\n\tconst shapeIdsToInclude = editor.getShapeAndDescendantIds(ids)\n\tconst renderingShapes = editor\n\t\t.getUnorderedRenderingShapes(false)\n\t\t.filter(({ id }) => shapeIdsToInclude.has(id))\n\n\t// --- Common bounding box of all shapes\n\tlet bbox: null | Box = null\n\tif (opts.bounds) {\n\t\tbbox = opts.bounds\n\t} else {\n\t\tfor (const { id } of renderingShapes) {\n\t\t\tconst maskedPageBounds = editor.getShapeMaskedPageBounds(id)\n\t\t\tif (!maskedPageBounds) continue\n\t\t\tif (bbox) {\n\t\t\t\tbbox.union(maskedPageBounds)\n\t\t\t} else {\n\t\t\t\tbbox = maskedPageBounds.clone()\n\t\t\t}\n\t\t}\n\t}\n\n\t// no unmasked shapes to export\n\tif (!bbox) return\n\n\tconst singleFrameShapeId =\n\t\tids.length === 1 && editor.isShapeOfType<TLFrameShape>(editor.getShape(ids[0])!, 'frame')\n\t\t\t? ids[0]\n\t\t\t: null\n\tif (!singleFrameShapeId) {\n\t\t// Expand by an extra 32 pixels\n\t\tbbox.expandBy(padding)\n\t}\n\n\t// We want the svg image to be BIGGER THAN USUAL to account for image quality\n\tconst w = bbox.width * scale\n\tconst h = bbox.height * scale\n\n\ttry {\n\t\tdocument.body.focus?.() // weird but necessary\n\t} catch {\n\t\t// not implemented\n\t}\n\n\tconst exportDelay = new ExportDelay(editor.options.maxExportDelayMs)\n\n\tconst initialEffectPromise = promiseWithResolve<void>()\n\texportDelay.waitUntil(initialEffectPromise)\n\n\tconst svg = (\n\t\t<SvgExport\n\t\t\teditor={editor}\n\t\t\tpreserveAspectRatio={preserveAspectRatio}\n\t\t\tscale={scale}\n\t\t\tpixelRatio={opts.pixelRatio ?? null}\n\t\t\tbbox={bbox}\n\t\t\tbackground={background}\n\t\t\tsingleFrameShapeId={singleFrameShapeId}\n\t\t\tisDarkMode={isDarkMode}\n\t\t\trenderingShapes={renderingShapes}\n\t\t\tonMount={initialEffectPromise.resolve}\n\t\t\twaitUntil={exportDelay.waitUntil}\n\t\t>\n\t\t\t{}\n\t\t</SvgExport>\n\t)\n\n\treturn { jsx: svg, width: w, height: h, exportDelay }\n}\n\nfunction SvgExport({\n\teditor,\n\tpreserveAspectRatio,\n\tscale,\n\tpixelRatio,\n\tbbox,\n\tbackground,\n\tsingleFrameShapeId,\n\tisDarkMode,\n\trenderingShapes,\n\tonMount,\n\twaitUntil,\n}: {\n\teditor: Editor\n\tpreserveAspectRatio?: string\n\tscale: number\n\tpixelRatio: number | null\n\tbbox: Box\n\tbackground: boolean\n\tsingleFrameShapeId: TLShapeId | null\n\tisDarkMode: boolean\n\trenderingShapes: TLRenderingShape[]\n\tonMount(): void\n\twaitUntil(promise: Promise<void>): void\n}) {\n\tconst masksId = useUniqueSafeId()\n\tconst theme = getDefaultColorTheme({ isDarkMode })\n\n\tconst stateAtom = useAtom<{\n\t\tdefsById: Record<\n\t\t\tstring,\n\t\t\t{ pending: false; element: ReactNode } | { pending: true; element: Promise<ReactNode> }\n\t\t>\n\t\tshapeElements: ReactElement[] | null\n\t}>('export state', { defsById: {}, shapeElements: null })\n\tconst { defsById, shapeElements } = useValue(stateAtom)\n\n\tconst addExportDef = useEvent((def: SvgExportDef) => {\n\t\tstateAtom.update((state) => {\n\t\t\tif (hasOwnProperty(state.defsById, def.key)) return state\n\n\t\t\tconst promise = Promise.resolve(def.getElement())\n\t\t\twaitUntil(\n\t\t\t\tpromise.then((result) => {\n\t\t\t\t\tstateAtom.update((state) => ({\n\t\t\t\t\t\t...state,\n\t\t\t\t\t\tdefsById: { ...state.defsById, [def.key]: { pending: false, element: result } },\n\t\t\t\t\t}))\n\t\t\t\t})\n\t\t\t)\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tdefsById: { ...state.defsById, [def.key]: { pending: true, element: promise } },\n\t\t\t}\n\t\t})\n\t})\n\n\tconst exportContext = useMemo(\n\t\t(): SvgExportContext => ({\n\t\t\tisDarkMode,\n\t\t\twaitUntil,\n\t\t\taddExportDef,\n\t\t\tscale,\n\t\t\tpixelRatio,\n\t\t\tasync resolveAssetUrl(assetId, width) {\n\t\t\t\tconst asset = editor.getAsset(assetId)\n\t\t\t\tif (!asset || (asset.type !== 'image' && asset.type !== 'video')) return null\n\n\t\t\t\treturn await editor.resolveAssetUrl(assetId, {\n\t\t\t\t\tscreenScale: scale * (width / asset.props.w),\n\t\t\t\t\tshouldResolveToOriginal: pixelRatio === null,\n\t\t\t\t\tdpr: pixelRatio ?? undefined,\n\t\t\t\t})\n\t\t\t},\n\t\t}),\n\t\t[isDarkMode, waitUntil, addExportDef, scale, pixelRatio, editor]\n\t)\n\n\tconst didRenderRef = useRef(false)\n\tuseLayoutEffect(() => {\n\t\tif (didRenderRef.current) {\n\t\t\tthrow new Error('SvgExport should only render once - do not use with react strict mode')\n\t\t}\n\t\tdidRenderRef.current = true\n\t\t;(async () => {\n\t\t\tconst shapeDefs: Record<string, { pending: false; element: ReactElement }> = {}\n\n\t\t\t// Then render everything. The shapes with assets should all hit the cache\n\t\t\tconst unorderedShapeElementPromises = renderingShapes.map(\n\t\t\t\tasync ({ id, opacity, index, backgroundIndex }) => {\n\t\t\t\t\t// Don't render the frame if we're only exporting a single frame and it's children\n\t\t\t\t\tif (id === singleFrameShapeId) return []\n\n\t\t\t\t\tconst shape = editor.getShape(id)!\n\n\t\t\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) return []\n\n\t\t\t\t\tconst elements = []\n\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\n\t\t\t\t\tif (util.toSvg || util.toBackgroundSvg) {\n\t\t\t\t\t\t// If the shape has any sort of custom svg export, let's use that.\n\t\t\t\t\t\tconst [toSvgResult, toBackgroundSvgResult] = await Promise.all([\n\t\t\t\t\t\t\tutil.toSvg?.(shape, exportContext),\n\t\t\t\t\t\t\tutil.toBackgroundSvg?.(shape, exportContext),\n\t\t\t\t\t\t])\n\n\t\t\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\t\t\t\tlet pageTransformString = pageTransform!.toCssString()\n\t\t\t\t\t\tlet scale = 1\n\t\t\t\t\t\tif ('scale' in shape.props) {\n\t\t\t\t\t\t\tif (shape.props.scale !== 1) {\n\t\t\t\t\t\t\t\tscale = shape.props.scale\n\t\t\t\t\t\t\t\tpageTransformString = `${pageTransformString} scale(${shape.props.scale}, ${shape.props.scale})`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Create svg mask if shape has a frame as parent\n\t\t\t\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\t\t\t\tconst shapeMask = pageMask\n\t\t\t\t\t\t\t? Mat.From(Mat.Inverse(pageTransform)).applyToPoints(pageMask)\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tconst shapeMaskId = suffixSafeId(masksId, shape.id)\n\t\t\t\t\t\tif (shapeMask) {\n\t\t\t\t\t\t\t// Create a clip path and add it to defs\n\t\t\t\t\t\t\tshapeDefs[shapeMaskId] = {\n\t\t\t\t\t\t\t\tpending: false,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<clipPath id={shapeMaskId}>\n\t\t\t\t\t\t\t\t\t\t{/* Create a polyline mask that does the clipping */}\n\t\t\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\t\t\td={`M${shapeMask.map(({ x, y }) => `${x / scale},${y / scale}`).join('L')}Z`}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</clipPath>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (toSvgResult) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: index,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\t\t\tkey={`fg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\ttransform={pageTransformString}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t\tclipPath={pageMask ? `url(#${shapeMaskId})` : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{toSvgResult}\n\t\t\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (toBackgroundSvgResult) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: backgroundIndex,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\t\t\tkey={`bg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\ttransform={pageTransformString}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t\tclipPath={pageMask ? `url(#${shapeMaskId})` : undefined}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{toBackgroundSvgResult}\n\t\t\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If the shape doesn't have a custom svg export, we'll use its normal HTML\n\t\t\t\t\t\t// renderer in a foreignObject.\n\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\tzIndex: index,\n\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t<ForeignObjectShape\n\t\t\t\t\t\t\t\t\tkey={`fg_${shape.id}`}\n\t\t\t\t\t\t\t\t\tshape={shape}\n\t\t\t\t\t\t\t\t\tutil={util}\n\t\t\t\t\t\t\t\t\tcomponent={InnerShape}\n\t\t\t\t\t\t\t\t\tclassName=\"tl-shape\"\n\t\t\t\t\t\t\t\t\tbbox={bbox}\n\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (util.backgroundComponent) {\n\t\t\t\t\t\t\telements.push({\n\t\t\t\t\t\t\t\tzIndex: backgroundIndex,\n\t\t\t\t\t\t\t\telement: (\n\t\t\t\t\t\t\t\t\t<ForeignObjectShape\n\t\t\t\t\t\t\t\t\t\tkey={`bg_${shape.id}`}\n\t\t\t\t\t\t\t\t\t\tshape={shape}\n\t\t\t\t\t\t\t\t\t\tutil={util}\n\t\t\t\t\t\t\t\t\t\tcomponent={InnerShapeBackground}\n\t\t\t\t\t\t\t\t\t\tclassName=\"tl-shape tl-shape-background\"\n\t\t\t\t\t\t\t\t\t\tbbox={bbox}\n\t\t\t\t\t\t\t\t\t\topacity={opacity}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn elements\n\t\t\t\t}\n\t\t\t)\n\n\t\t\tconst unorderedShapeElements = (await Promise.all(unorderedShapeElementPromises)).flat()\n\n\t\t\tflushSync(() => {\n\t\t\t\tstateAtom.update((state) => ({\n\t\t\t\t\t...state,\n\t\t\t\t\tshapeElements: unorderedShapeElements\n\t\t\t\t\t\t.sort((a, b) => a.zIndex - b.zIndex)\n\t\t\t\t\t\t.map(({ element }) => element),\n\t\t\t\t\tdefsById: { ...state.defsById, ...shapeDefs },\n\t\t\t\t}))\n\t\t\t})\n\t\t})()\n\t}, [bbox, editor, exportContext, masksId, renderingShapes, singleFrameShapeId, stateAtom])\n\n\tuseEffect(() => {\n\t\tconst fontsInUse = new Set<TLFontFace>()\n\t\tfor (const { id } of renderingShapes) {\n\t\t\tfor (const font of editor.fonts.getShapeFontFaces(id)) {\n\t\t\t\tfontsInUse.add(font)\n\t\t\t}\n\t\t}\n\n\t\tfor (const font of fontsInUse) {\n\t\t\taddExportDef({\n\t\t\t\tkey: uniqueId(),\n\t\t\t\tgetElement: async () => {\n\t\t\t\t\tconst declaration = await editor.fonts.toEmbeddedCssDeclaration(font)\n\t\t\t\t\treturn <style nonce={editor.options.nonce}>{declaration}</style>\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}, [editor, renderingShapes, addExportDef])\n\n\tuseEffect(() => {\n\t\tif (shapeElements === null) return\n\t\tonMount()\n\t}, [onMount, shapeElements])\n\n\treturn (\n\t\t<SvgExportContextProvider editor={editor} context={exportContext}>\n\t\t\t<svg\n\t\t\t\tpreserveAspectRatio={preserveAspectRatio}\n\t\t\t\tdirection=\"ltr\"\n\t\t\t\twidth={bbox.width * scale}\n\t\t\t\theight={bbox.height * scale}\n\t\t\t\tviewBox={`${bbox.minX} ${bbox.minY} ${bbox.width} ${bbox.height}`}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: background\n\t\t\t\t\t\t? singleFrameShapeId\n\t\t\t\t\t\t\t? theme.solid\n\t\t\t\t\t\t\t: theme.background\n\t\t\t\t\t\t: 'transparent',\n\t\t\t\t}}\n\t\t\t\tdata-color-mode={isDarkMode ? 'dark' : 'light'}\n\t\t\t\tclassName={`tl-container tl-theme__force-sRGB ${isDarkMode ? 'tl-theme__dark' : 'tl-theme__light'}`}\n\t\t\t>\n\t\t\t\t<defs>\n\t\t\t\t\t{Object.entries(defsById).map(([key, def]) =>\n\t\t\t\t\t\tdef.pending ? null : <Fragment key={key}>{def.element}</Fragment>\n\t\t\t\t\t)}\n\t\t\t\t</defs>\n\t\t\t\t{shapeElements}\n\t\t\t</svg>\n\t\t</SvgExportContextProvider>\n\t)\n}\n\nfunction ForeignObjectShape({\n\tshape,\n\tutil,\n\tclassName,\n\tcomponent: Component,\n\tbbox,\n\topacity,\n}: {\n\tshape: TLShape\n\tutil: ShapeUtil\n\tclassName?: string\n\tcomponent: ComponentType<{ shape: TLShape; util: ShapeUtil }>\n\tbbox: Box\n\topacity: number\n}) {\n\tconst editor = useEditor()\n\n\tconst transform = Mat.Translate(-bbox.minX, -bbox.minY).multiply(\n\t\teditor.getShapePageTransform(shape.id)!\n\t)\n\n\tconst bounds = editor.getShapeGeometry(shape.id).bounds\n\tconst width = Math.max(bounds.width, 1)\n\tconst height = Math.max(bounds.height, 1)\n\n\treturn (\n\t\t<ErrorBoundary fallback={() => null}>\n\t\t\t<foreignObject\n\t\t\t\tx={bbox.minX}\n\t\t\t\ty={bbox.minY}\n\t\t\t\twidth={bbox.w}\n\t\t\t\theight={bbox.h}\n\t\t\t\tclassName=\"tl-shape-foreign-object tl-export-embed-styles\"\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tdata-shape-type={shape.type}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tclipPath: editor.getShapeClipPath(shape.id),\n\t\t\t\t\t\ttransform: transform.toCssString(),\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\topacity,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<Component shape={shape} util={util} />\n\t\t\t\t</div>\n\t\t\t</foreignObject>\n\t\t</ErrorBoundary>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["state", "scale"]
7
7
  }
@@ -67,11 +67,33 @@ function parseCssValueUrls(value) {
67
67
  url: m[1] || m[2] || m[3]
68
68
  }));
69
69
  }
70
+ const currentColorProperties = /* @__PURE__ */ new Set([
71
+ "border-block-end-color",
72
+ "border-block-start-color",
73
+ "border-bottom-color",
74
+ "border-inline-end-color",
75
+ "border-inline-start-color",
76
+ "border-left-color",
77
+ "border-right-color",
78
+ "border-top-color",
79
+ "caret-color",
80
+ "column-rule-color",
81
+ "outline-color",
82
+ "text-decoration",
83
+ "text-decoration-color",
84
+ "text-emphasis-color"
85
+ ]);
86
+ function isPropertyCoveredByCurrentColor(currentColor, property, value) {
87
+ if (currentColorProperties.has(property)) {
88
+ return value === "currentColor" || value === currentColor || property === "text-decoration" && value === `none solid ${currentColor}`;
89
+ }
90
+ }
70
91
  const inheritedProperties = /* @__PURE__ */ new Set([
71
92
  "border-collapse",
72
93
  "border-spacing",
73
94
  "caption-side",
74
- "color",
95
+ // N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
96
+ // 'color',
75
97
  "cursor",
76
98
  "direction",
77
99
  "empty-cells",
@@ -92,16 +114,18 @@ const inheritedProperties = /* @__PURE__ */ new Set([
92
114
  "orphans",
93
115
  "overflow-wrap",
94
116
  "quotes",
117
+ "stroke-linecap",
118
+ "stroke-linejoin",
95
119
  "tab-size",
96
120
  "text-align",
97
121
  "text-align-last",
98
- "text-decoration-color",
99
122
  "text-indent",
100
123
  "text-justify",
101
124
  "text-shadow",
102
125
  "text-transform",
103
126
  "visibility",
104
127
  "white-space",
128
+ "white-space-collapse",
105
129
  "widows",
106
130
  "word-break",
107
131
  "word-spacing",
@@ -111,6 +135,7 @@ function isPropertyInherited(property) {
111
135
  return inheritedProperties.has(property);
112
136
  }
113
137
  export {
138
+ isPropertyCoveredByCurrentColor,
114
139
  isPropertyInherited,
115
140
  parseCss,
116
141
  parseCssFontFaces,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/exports/parseCss.ts"],
4
- "sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\n\nexport interface ParsedFontFace {\n\tfontFace: string\n\turls: { original: string; resolved: string | null; embedded?: Promise<string | null> }[]\n\tfontFamilies: Set<string>\n}\n\n// parsing CSS with regular expressions doesn't really work. There are almost certainly edge cases\n// in the regular expressions we're using here. They're based formal grammars of CSS, but aren't\n// perfect. These were written with https://regexper.com/ - give it a go if you're editing these.\n\n// The regexes themselves would be nicer to work with if we were using named capturing groups\n// (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group).\n// We use a lot of disjunctions (the `|`) to cover different syntaxes though, and at the time of\n// writing, browser support for using named capturing groups across disjunctions is rough.\n\n// Parse @import declarations:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/@import#formal_syntax\nconst importsRegex =\n\t/@import\\s+(?:\"([^\"]+)\"|'([^']+)'|url\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^'\")]+))\\s*\\))([^;]+);/gi\n\n// Locate @font-face declarations:\nconst fontFaceRegex = /@font-face\\s*{([^}]+)}/gi\n\n// Parse url() calls within a CSS value:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax\nconst urlsRegex = /url\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^'\")]+))\\s*\\)/gi\n\n// Locate and parse the value of `font-family` within a @font-face declaration:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family#formal_syntax\nconst fontFamilyRegex =\n\t/(?:^|;)\\s*font-family\\s*:\\s*(?:([^'\"][^;\\n]+)|\"([^\"]+)\"|'([^']+)')\\s*(?:;|$)/gi\n\nexport function parseCssImports(css: string) {\n\treturn Array.from(css.matchAll(importsRegex), (m) => ({\n\t\turl: m[1] || m[2] || m[3] || m[4] || m[5],\n\t\textras: m[6],\n\t}))\n}\n\nexport function parseCssFontFaces(css: string, baseUrl: string) {\n\treturn Array.from(css.matchAll(fontFaceRegex), (m): ParsedFontFace => {\n\t\tconst fontFace = m[1]\n\t\tconst urls = Array.from(fontFace.matchAll(urlsRegex), (m) => {\n\t\t\tconst original = m[1] || m[2] || m[3]\n\t\t\treturn {\n\t\t\t\toriginal,\n\t\t\t\tresolved: safeParseUrl(original, baseUrl)?.href ?? null,\n\t\t\t}\n\t\t})\n\t\tconst fontFamilies = new Set(\n\t\t\tArray.from(fontFace.matchAll(fontFamilyRegex), (m) => (m[1] || m[2] || m[3]).toLowerCase())\n\t\t)\n\n\t\treturn { fontFace, urls, fontFamilies }\n\t})\n}\n\nexport function parseCssFontFamilyValue(value: string) {\n\t// https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#formal_syntax\n\t// we use two regexes here to parse each value in a comma separated list of font families\n\tconst valueRegex = /\\s*(?:([^'\"][^;\\n\\s,]+)|\"([^\"]+)\"|'([^']+)')\\s*/gi\n\tconst separatorRegex = /\\s*,\\s*/gi\n\n\tconst fontFamilies = new Set<string>()\n\n\twhile (true) {\n\t\tconst valueMatch = valueRegex.exec(value)\n\t\tif (!valueMatch) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst fontFamily = valueMatch[1] || valueMatch[2] || valueMatch[3]\n\t\tfontFamilies.add(fontFamily.toLowerCase())\n\n\t\tseparatorRegex.lastIndex = valueRegex.lastIndex\n\t\tconst separatorMatch = separatorRegex.exec(value)\n\t\tif (!separatorMatch) {\n\t\t\tbreak\n\t\t}\n\n\t\tvalueRegex.lastIndex = separatorRegex.lastIndex\n\t}\n\n\treturn fontFamilies\n}\n\nexport function shouldIncludeCssProperty(property: string) {\n\tif (property.startsWith('-')) return false\n\tif (property.startsWith('animation')) return false\n\tif (property.startsWith('transition')) return false\n\tif (property === 'cursor') return false\n\tif (property === 'pointer-events') return false\n\tif (property === 'user-select') return false\n\tif (property === 'touch-action') return false\n\treturn true\n}\n\nexport function parseCss(css: string, baseUrl: string) {\n\treturn {\n\t\timports: parseCssImports(css),\n\t\tfontFaces: parseCssFontFaces(css, baseUrl),\n\t}\n}\n\nexport function parseCssValueUrls(value: string) {\n\treturn Array.from(value.matchAll(urlsRegex), (m) => ({\n\t\toriginal: m[0],\n\t\turl: m[1] || m[2] || m[3],\n\t}))\n}\n\nconst inheritedProperties = new Set([\n\t'border-collapse',\n\t'border-spacing',\n\t'caption-side',\n\t'color',\n\t'cursor',\n\t'direction',\n\t'empty-cells',\n\t'font-family',\n\t'font-size',\n\t'font-style',\n\t'font-variant',\n\t'font-weight',\n\t'font-size-adjust',\n\t'font-stretch',\n\t'font',\n\t'letter-spacing',\n\t'line-height',\n\t'list-style-image',\n\t'list-style-position',\n\t'list-style-type',\n\t'list-style',\n\t'orphans',\n\t'overflow-wrap',\n\t'quotes',\n\t'tab-size',\n\t'text-align',\n\t'text-align-last',\n\t'text-decoration-color',\n\t'text-indent',\n\t'text-justify',\n\t'text-shadow',\n\t'text-transform',\n\t'visibility',\n\t'white-space',\n\t'widows',\n\t'word-break',\n\t'word-spacing',\n\t'word-wrap',\n])\n\nexport function isPropertyInherited(property: string) {\n\treturn inheritedProperties.has(property)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\n\nexport interface ParsedFontFace {\n\tfontFace: string\n\turls: { original: string; resolved: string | null; embedded?: Promise<string | null> }[]\n\tfontFamilies: Set<string>\n}\n\n// parsing CSS with regular expressions doesn't really work. There are almost certainly edge cases\n// in the regular expressions we're using here. They're based formal grammars of CSS, but aren't\n// perfect. These were written with https://regexper.com/ - give it a go if you're editing these.\n\n// The regexes themselves would be nicer to work with if we were using named capturing groups\n// (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group).\n// We use a lot of disjunctions (the `|`) to cover different syntaxes though, and at the time of\n// writing, browser support for using named capturing groups across disjunctions is rough.\n\n// Parse @import declarations:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/@import#formal_syntax\nconst importsRegex =\n\t/@import\\s+(?:\"([^\"]+)\"|'([^']+)'|url\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^'\")]+))\\s*\\))([^;]+);/gi\n\n// Locate @font-face declarations:\nconst fontFaceRegex = /@font-face\\s*{([^}]+)}/gi\n\n// Parse url() calls within a CSS value:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/url#syntax\nconst urlsRegex = /url\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^'\")]+))\\s*\\)/gi\n\n// Locate and parse the value of `font-family` within a @font-face declaration:\n// https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family#formal_syntax\nconst fontFamilyRegex =\n\t/(?:^|;)\\s*font-family\\s*:\\s*(?:([^'\"][^;\\n]+)|\"([^\"]+)\"|'([^']+)')\\s*(?:;|$)/gi\n\nexport function parseCssImports(css: string) {\n\treturn Array.from(css.matchAll(importsRegex), (m) => ({\n\t\turl: m[1] || m[2] || m[3] || m[4] || m[5],\n\t\textras: m[6],\n\t}))\n}\n\nexport function parseCssFontFaces(css: string, baseUrl: string) {\n\treturn Array.from(css.matchAll(fontFaceRegex), (m): ParsedFontFace => {\n\t\tconst fontFace = m[1]\n\t\tconst urls = Array.from(fontFace.matchAll(urlsRegex), (m) => {\n\t\t\tconst original = m[1] || m[2] || m[3]\n\t\t\treturn {\n\t\t\t\toriginal,\n\t\t\t\tresolved: safeParseUrl(original, baseUrl)?.href ?? null,\n\t\t\t}\n\t\t})\n\t\tconst fontFamilies = new Set(\n\t\t\tArray.from(fontFace.matchAll(fontFamilyRegex), (m) => (m[1] || m[2] || m[3]).toLowerCase())\n\t\t)\n\n\t\treturn { fontFace, urls, fontFamilies }\n\t})\n}\n\nexport function parseCssFontFamilyValue(value: string) {\n\t// https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#formal_syntax\n\t// we use two regexes here to parse each value in a comma separated list of font families\n\tconst valueRegex = /\\s*(?:([^'\"][^;\\n\\s,]+)|\"([^\"]+)\"|'([^']+)')\\s*/gi\n\tconst separatorRegex = /\\s*,\\s*/gi\n\n\tconst fontFamilies = new Set<string>()\n\n\twhile (true) {\n\t\tconst valueMatch = valueRegex.exec(value)\n\t\tif (!valueMatch) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst fontFamily = valueMatch[1] || valueMatch[2] || valueMatch[3]\n\t\tfontFamilies.add(fontFamily.toLowerCase())\n\n\t\tseparatorRegex.lastIndex = valueRegex.lastIndex\n\t\tconst separatorMatch = separatorRegex.exec(value)\n\t\tif (!separatorMatch) {\n\t\t\tbreak\n\t\t}\n\n\t\tvalueRegex.lastIndex = separatorRegex.lastIndex\n\t}\n\n\treturn fontFamilies\n}\n\nexport function shouldIncludeCssProperty(property: string) {\n\tif (property.startsWith('-')) return false\n\tif (property.startsWith('animation')) return false\n\tif (property.startsWith('transition')) return false\n\tif (property === 'cursor') return false\n\tif (property === 'pointer-events') return false\n\tif (property === 'user-select') return false\n\tif (property === 'touch-action') return false\n\treturn true\n}\n\nexport function parseCss(css: string, baseUrl: string) {\n\treturn {\n\t\timports: parseCssImports(css),\n\t\tfontFaces: parseCssFontFaces(css, baseUrl),\n\t}\n}\n\nexport function parseCssValueUrls(value: string) {\n\treturn Array.from(value.matchAll(urlsRegex), (m) => ({\n\t\toriginal: m[0],\n\t\turl: m[1] || m[2] || m[3],\n\t}))\n}\n\nconst currentColorProperties = new Set([\n\t'border-block-end-color',\n\t'border-block-start-color',\n\t'border-bottom-color',\n\t'border-inline-end-color',\n\t'border-inline-start-color',\n\t'border-left-color',\n\t'border-right-color',\n\t'border-top-color',\n\t'caret-color',\n\t'column-rule-color',\n\t'outline-color',\n\t'text-decoration',\n\t'text-decoration-color',\n\t'text-emphasis-color',\n])\n\nexport function isPropertyCoveredByCurrentColor(\n\tcurrentColor: string,\n\tproperty: string,\n\tvalue: string\n) {\n\tif (currentColorProperties.has(property)) {\n\t\treturn (\n\t\t\tvalue === 'currentColor' ||\n\t\t\tvalue === currentColor ||\n\t\t\t(property === 'text-decoration' && value === `none solid ${currentColor}`)\n\t\t)\n\t}\n}\n\nconst inheritedProperties = new Set([\n\t'border-collapse',\n\t'border-spacing',\n\t'caption-side',\n\t// N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements\n\t// 'color',\n\t'cursor',\n\t'direction',\n\t'empty-cells',\n\t'font-family',\n\t'font-size',\n\t'font-style',\n\t'font-variant',\n\t'font-weight',\n\t'font-size-adjust',\n\t'font-stretch',\n\t'font',\n\t'letter-spacing',\n\t'line-height',\n\t'list-style-image',\n\t'list-style-position',\n\t'list-style-type',\n\t'list-style',\n\t'orphans',\n\t'overflow-wrap',\n\t'quotes',\n\t'stroke-linecap',\n\t'stroke-linejoin',\n\t'tab-size',\n\t'text-align',\n\t'text-align-last',\n\t'text-indent',\n\t'text-justify',\n\t'text-shadow',\n\t'text-transform',\n\t'visibility',\n\t'white-space',\n\t'white-space-collapse',\n\t'widows',\n\t'word-break',\n\t'word-spacing',\n\t'word-wrap',\n])\n\nexport function isPropertyInherited(property: string) {\n\treturn inheritedProperties.has(property)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["m"]
7
7
  }
@@ -34,6 +34,9 @@ function useLocalStore(options) {
34
34
  }
35
35
  return asset.props.src;
36
36
  },
37
+ remove: async (assetIds) => {
38
+ await client.db.removeAssets(assetIds);
39
+ },
37
40
  ...rest.assets
38
41
  };
39
42
  const store = createTLStore({ ...rest, assets });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useLocalStore.ts"],
4
- "sourcesContent": ["import { TLAsset, TLAssetStore, TLStoreSnapshot } from '@tldraw/tlschema'\nimport { WeakCache } from '@tldraw/utils'\nimport { useEffect } from 'react'\nimport { TLEditorSnapshot } from '../config/TLEditorSnapshot'\nimport { TLStoreOptions, createTLStore } from '../config/createTLStore'\nimport { TLStoreWithStatus } from '../utils/sync/StoreWithStatus'\nimport { TLLocalSyncClient } from '../utils/sync/TLLocalSyncClient'\nimport { useShallowObjectIdentity } from './useIdentity'\nimport { useRefState } from './useRefState'\n\n/** @internal */\nexport function useLocalStore(\n\toptions: {\n\t\tpersistenceKey?: string\n\t\tsessionId?: string\n\t\tsnapshot?: TLEditorSnapshot | TLStoreSnapshot\n\t} & TLStoreOptions\n): TLStoreWithStatus {\n\tconst [state, setState] = useRefState<TLStoreWithStatus>({ status: 'loading' })\n\n\toptions = useShallowObjectIdentity(options)\n\n\tuseEffect(() => {\n\t\tconst { persistenceKey, sessionId, ...rest } = options\n\n\t\tif (!persistenceKey) {\n\t\t\tsetState({\n\t\t\t\tstatus: 'not-synced',\n\t\t\t\tstore: createTLStore(rest),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tsetState({ status: 'loading' })\n\n\t\tconst objectURLCache = new WeakCache<TLAsset, Promise<string | null>>()\n\t\tconst assets: TLAssetStore = {\n\t\t\tupload: async (asset, file) => {\n\t\t\t\tawait client.db.storeAsset(asset.id, file)\n\t\t\t\treturn { src: asset.id }\n\t\t\t},\n\t\t\tresolve: async (asset) => {\n\t\t\t\tif (!asset.props.src) return null\n\n\t\t\t\tif (asset.props.src.startsWith('asset:')) {\n\t\t\t\t\treturn await objectURLCache.get(asset, async () => {\n\t\t\t\t\t\tconst blob = await client.db.getAsset(asset.id)\n\t\t\t\t\t\tif (!blob) return null\n\t\t\t\t\t\treturn URL.createObjectURL(blob)\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\treturn asset.props.src\n\t\t\t},\n\t\t\t...rest.assets,\n\t\t}\n\n\t\tconst store = createTLStore({ ...rest, assets })\n\n\t\tlet isClosed = false\n\n\t\tconst client = new TLLocalSyncClient(store, {\n\t\t\tsessionId,\n\t\t\tpersistenceKey,\n\t\t\tonLoad() {\n\t\t\t\tif (isClosed) return\n\t\t\t\tsetState({ store, status: 'synced-local' })\n\t\t\t},\n\t\t\tonLoadError(err: any) {\n\t\t\t\tif (isClosed) return\n\t\t\t\tsetState({ status: 'error', error: err })\n\t\t\t},\n\t\t})\n\n\t\treturn () => {\n\t\t\tisClosed = true\n\t\t\tclient.close()\n\t\t}\n\t}, [options, setState])\n\n\treturn state\n}\n"],
5
- "mappings": "AACA,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAE1B,SAAyB,qBAAqB;AAE9C,SAAS,yBAAyB;AAClC,SAAS,gCAAgC;AACzC,SAAS,mBAAmB;AAGrB,SAAS,cACf,SAKoB;AACpB,QAAM,CAAC,OAAO,QAAQ,IAAI,YAA+B,EAAE,QAAQ,UAAU,CAAC;AAE9E,YAAU,yBAAyB,OAAO;AAE1C,YAAU,MAAM;AACf,UAAM,EAAE,gBAAgB,WAAW,GAAG,KAAK,IAAI;AAE/C,QAAI,CAAC,gBAAgB;AACpB,eAAS;AAAA,QACR,QAAQ;AAAA,QACR,OAAO,cAAc,IAAI;AAAA,MAC1B,CAAC;AACD;AAAA,IACD;AAEA,aAAS,EAAE,QAAQ,UAAU,CAAC;AAE9B,UAAM,iBAAiB,IAAI,UAA2C;AACtE,UAAM,SAAuB;AAAA,MAC5B,QAAQ,OAAO,OAAO,SAAS;AAC9B,cAAM,OAAO,GAAG,WAAW,MAAM,IAAI,IAAI;AACzC,eAAO,EAAE,KAAK,MAAM,GAAG;AAAA,MACxB;AAAA,MACA,SAAS,OAAO,UAAU;AACzB,YAAI,CAAC,MAAM,MAAM,IAAK,QAAO;AAE7B,YAAI,MAAM,MAAM,IAAI,WAAW,QAAQ,GAAG;AACzC,iBAAO,MAAM,eAAe,IAAI,OAAO,YAAY;AAClD,kBAAM,OAAO,MAAM,OAAO,GAAG,SAAS,MAAM,EAAE;AAC9C,gBAAI,CAAC,KAAM,QAAO;AAClB,mBAAO,IAAI,gBAAgB,IAAI;AAAA,UAChC,CAAC;AAAA,QACF;AAEA,eAAO,MAAM,MAAM;AAAA,MACpB;AAAA,MACA,GAAG,KAAK;AAAA,IACT;AAEA,UAAM,QAAQ,cAAc,EAAE,GAAG,MAAM,OAAO,CAAC;AAE/C,QAAI,WAAW;AAEf,UAAM,SAAS,IAAI,kBAAkB,OAAO;AAAA,MAC3C;AAAA,MACA;AAAA,MACA,SAAS;AACR,YAAI,SAAU;AACd,iBAAS,EAAE,OAAO,QAAQ,eAAe,CAAC;AAAA,MAC3C;AAAA,MACA,YAAY,KAAU;AACrB,YAAI,SAAU;AACd,iBAAS,EAAE,QAAQ,SAAS,OAAO,IAAI,CAAC;AAAA,MACzC;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,iBAAW;AACX,aAAO,MAAM;AAAA,IACd;AAAA,EACD,GAAG,CAAC,SAAS,QAAQ,CAAC;AAEtB,SAAO;AACR;",
4
+ "sourcesContent": ["import { TLAsset, TLAssetStore, TLStoreSnapshot } from '@tldraw/tlschema'\nimport { WeakCache } from '@tldraw/utils'\nimport { useEffect } from 'react'\nimport { TLEditorSnapshot } from '../config/TLEditorSnapshot'\nimport { TLStoreOptions, createTLStore } from '../config/createTLStore'\nimport { TLStoreWithStatus } from '../utils/sync/StoreWithStatus'\nimport { TLLocalSyncClient } from '../utils/sync/TLLocalSyncClient'\nimport { useShallowObjectIdentity } from './useIdentity'\nimport { useRefState } from './useRefState'\n\n/** @internal */\nexport function useLocalStore(\n\toptions: {\n\t\tpersistenceKey?: string\n\t\tsessionId?: string\n\t\tsnapshot?: TLEditorSnapshot | TLStoreSnapshot\n\t} & TLStoreOptions\n): TLStoreWithStatus {\n\tconst [state, setState] = useRefState<TLStoreWithStatus>({ status: 'loading' })\n\n\toptions = useShallowObjectIdentity(options)\n\n\tuseEffect(() => {\n\t\tconst { persistenceKey, sessionId, ...rest } = options\n\n\t\tif (!persistenceKey) {\n\t\t\tsetState({\n\t\t\t\tstatus: 'not-synced',\n\t\t\t\tstore: createTLStore(rest),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tsetState({ status: 'loading' })\n\n\t\tconst objectURLCache = new WeakCache<TLAsset, Promise<string | null>>()\n\t\tconst assets: TLAssetStore = {\n\t\t\tupload: async (asset, file) => {\n\t\t\t\tawait client.db.storeAsset(asset.id, file)\n\t\t\t\treturn { src: asset.id }\n\t\t\t},\n\t\t\tresolve: async (asset) => {\n\t\t\t\tif (!asset.props.src) return null\n\n\t\t\t\tif (asset.props.src.startsWith('asset:')) {\n\t\t\t\t\treturn await objectURLCache.get(asset, async () => {\n\t\t\t\t\t\tconst blob = await client.db.getAsset(asset.id)\n\t\t\t\t\t\tif (!blob) return null\n\t\t\t\t\t\treturn URL.createObjectURL(blob)\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\treturn asset.props.src\n\t\t\t},\n\t\t\tremove: async (assetIds) => {\n\t\t\t\tawait client.db.removeAssets(assetIds)\n\t\t\t},\n\t\t\t...rest.assets,\n\t\t}\n\n\t\tconst store = createTLStore({ ...rest, assets })\n\n\t\tlet isClosed = false\n\n\t\tconst client = new TLLocalSyncClient(store, {\n\t\t\tsessionId,\n\t\t\tpersistenceKey,\n\t\t\tonLoad() {\n\t\t\t\tif (isClosed) return\n\t\t\t\tsetState({ store, status: 'synced-local' })\n\t\t\t},\n\t\t\tonLoadError(err: any) {\n\t\t\t\tif (isClosed) return\n\t\t\t\tsetState({ status: 'error', error: err })\n\t\t\t},\n\t\t})\n\n\t\treturn () => {\n\t\t\tisClosed = true\n\t\t\tclient.close()\n\t\t}\n\t}, [options, setState])\n\n\treturn state\n}\n"],
5
+ "mappings": "AACA,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAE1B,SAAyB,qBAAqB;AAE9C,SAAS,yBAAyB;AAClC,SAAS,gCAAgC;AACzC,SAAS,mBAAmB;AAGrB,SAAS,cACf,SAKoB;AACpB,QAAM,CAAC,OAAO,QAAQ,IAAI,YAA+B,EAAE,QAAQ,UAAU,CAAC;AAE9E,YAAU,yBAAyB,OAAO;AAE1C,YAAU,MAAM;AACf,UAAM,EAAE,gBAAgB,WAAW,GAAG,KAAK,IAAI;AAE/C,QAAI,CAAC,gBAAgB;AACpB,eAAS;AAAA,QACR,QAAQ;AAAA,QACR,OAAO,cAAc,IAAI;AAAA,MAC1B,CAAC;AACD;AAAA,IACD;AAEA,aAAS,EAAE,QAAQ,UAAU,CAAC;AAE9B,UAAM,iBAAiB,IAAI,UAA2C;AACtE,UAAM,SAAuB;AAAA,MAC5B,QAAQ,OAAO,OAAO,SAAS;AAC9B,cAAM,OAAO,GAAG,WAAW,MAAM,IAAI,IAAI;AACzC,eAAO,EAAE,KAAK,MAAM,GAAG;AAAA,MACxB;AAAA,MACA,SAAS,OAAO,UAAU;AACzB,YAAI,CAAC,MAAM,MAAM,IAAK,QAAO;AAE7B,YAAI,MAAM,MAAM,IAAI,WAAW,QAAQ,GAAG;AACzC,iBAAO,MAAM,eAAe,IAAI,OAAO,YAAY;AAClD,kBAAM,OAAO,MAAM,OAAO,GAAG,SAAS,MAAM,EAAE;AAC9C,gBAAI,CAAC,KAAM,QAAO;AAClB,mBAAO,IAAI,gBAAgB,IAAI;AAAA,UAChC,CAAC;AAAA,QACF;AAEA,eAAO,MAAM,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ,OAAO,aAAa;AAC3B,cAAM,OAAO,GAAG,aAAa,QAAQ;AAAA,MACtC;AAAA,MACA,GAAG,KAAK;AAAA,IACT;AAEA,UAAM,QAAQ,cAAc,EAAE,GAAG,MAAM,OAAO,CAAC;AAE/C,QAAI,WAAW;AAEf,UAAM,SAAS,IAAI,kBAAkB,OAAO;AAAA,MAC3C;AAAA,MACA;AAAA,MACA,SAAS;AACR,YAAI,SAAU;AACd,iBAAS,EAAE,OAAO,QAAQ,eAAe,CAAC;AAAA,MAC3C;AAAA,MACA,YAAY,KAAU;AACrB,YAAI,SAAU;AACd,iBAAS,EAAE,QAAQ,SAAS,OAAO,IAAI,CAAC;AAAA,MACzC;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,iBAAW;AACX,aAAO,MAAM;AAAA,IACd;AAAA,EACD,GAAG,CAAC,SAAS,QAAQ,CAAC;AAEtB,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -75,6 +75,7 @@ const WatermarkInner = memo(function WatermarkInner2({ src }) {
75
75
  );
76
76
  });
77
77
  const LicenseStyles = memo(function LicenseStyles2() {
78
+ const editor = useEditor();
78
79
  const className = LicenseManager.className;
79
80
  const CSS = `/* ------------------- SEE LICENSE -------------------
80
81
  The tldraw watermark is part of tldraw's license. It is shown for unlicensed
@@ -145,8 +146,13 @@ To remove the watermark, please purchase a license at tldraw.dev.
145
146
  animation: delayed_link 0.2s forwards ease-in-out;
146
147
  animation-delay: 0.32s;
147
148
  }
149
+
150
+ .${className} > a:focus-visible {
151
+ opacity: 1;
152
+ }
148
153
  }
149
154
 
155
+
150
156
  @keyframes delayed_link {
151
157
  0% {
152
158
  cursor: inherit;
@@ -159,7 +165,7 @@ To remove the watermark, please purchase a license at tldraw.dev.
159
165
  pointer-events: all;
160
166
  }
161
167
  }`;
162
- return /* @__PURE__ */ jsx("style", { children: CSS });
168
+ return /* @__PURE__ */ jsx("style", { nonce: editor.options.nonce, children: CSS });
163
169
  });
164
170
  export {
165
171
  Watermark