@tldraw/editor 3.16.0-canary.ba3bc37d4418 → 3.16.0-canary.bf7be9dad88b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-cjs/index.js CHANGED
@@ -371,7 +371,7 @@ var import_uniq = require("./lib/utils/uniq");
371
371
  var import_window_open = require("./lib/utils/window-open");
372
372
  (0, import_utils.registerTldrawLibraryVersion)(
373
373
  "@tldraw/editor",
374
- "3.16.0-canary.ba3bc37d4418",
374
+ "3.16.0-canary.bf7be9dad88b",
375
375
  "cjs"
376
376
  );
377
377
  //# sourceMappingURL=index.js.map
@@ -62,8 +62,10 @@ class FocusManager {
62
62
  }
63
63
  handleKeyDown(keyEvent) {
64
64
  const container = this.editor.getContainer();
65
- if (this.editor.isIn("select.editing_shape")) return;
66
- if (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return;
65
+ const activeEl = document.activeElement;
66
+ if (this.editor.isIn("select.editing_shape") && !activeEl?.closest(".tlui-contextual-toolbar"))
67
+ return;
68
+ if (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return;
67
69
  if (["Tab", "ArrowUp", "ArrowDown"].includes(keyEvent.key)) {
68
70
  container.classList.remove("tl-container__no-focus-ring");
69
71
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/managers/FocusManager/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\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 (this.editor.isIn('select.editing_shape')) return\n\t\tif (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return\n\t\tif (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {\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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;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,KAAK,OAAO,KAAK,sBAAsB,EAAG;AAC9C,QAAI,SAAS,kBAAkB,aAAa,KAAK,OAAO,oBAAoB,EAAE,SAAS,EAAG;AAC1F,QAAI,CAAC,OAAO,WAAW,WAAW,EAAE,SAAS,SAAS,GAAG,GAAG;AAC3D,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;",
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\tconst activeEl = document.activeElement\n\t\t// Edit mode should remove the focus ring, however if the active element's\n\t\t// parent is the contextual toolbar, then allow it.\n\t\tif (this.editor.isIn('select.editing_shape') && !activeEl?.closest('.tlui-contextual-toolbar'))\n\t\t\treturn\n\t\tif (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return\n\t\tif (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {\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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;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,UAAM,WAAW,SAAS;AAG1B,QAAI,KAAK,OAAO,KAAK,sBAAsB,KAAK,CAAC,UAAU,QAAQ,0BAA0B;AAC5F;AACD,QAAI,aAAa,aAAa,KAAK,OAAO,oBAAoB,EAAE,SAAS,EAAG;AAC5E,QAAI,CAAC,OAAO,WAAW,WAAW,EAAE,SAAS,SAAS,GAAG,GAAG;AAC3D,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
  }
@@ -61,7 +61,7 @@ const UnlicensedWatermark = (0, import_react.memo)(function UnlicensedWatermark2
61
61
  const events = (0, import_useCanvasEvents.useCanvasEvents)();
62
62
  const ref = (0, import_react.useRef)(null);
63
63
  (0, import_usePassThroughWheelEvents.usePassThroughWheelEvents)(ref);
64
- const url = "https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark";
64
+ const url = "https://tldraw.dev/pricing?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark";
65
65
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
66
66
  "div",
67
67
  {
@@ -82,22 +82,9 @@ const UnlicensedWatermark = (0, import_react.memo)(function UnlicensedWatermark2
82
82
  (0, import_dom.markEventAsHandled)(e);
83
83
  (0, import_dom.preventDefault)(e);
84
84
  },
85
- title: "Unlicensed - click to get a license",
85
+ title: "The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing.",
86
86
  onClick: () => import_runtime.runtime.openWindow(url, "_blank"),
87
- style: {
88
- position: "absolute",
89
- pointerEvents: "all",
90
- cursor: "pointer",
91
- color: "var(--tl-color-text)",
92
- opacity: 0.8,
93
- border: 0,
94
- padding: 0,
95
- backgroundColor: "transparent",
96
- fontSize: "11px",
97
- fontWeight: "600",
98
- textAlign: "center"
99
- },
100
- children: "Unlicensed"
87
+ children: "Get a license for production"
101
88
  }
102
89
  )
103
90
  }
@@ -139,7 +126,7 @@ const WatermarkInner = (0, import_react.memo)(function WatermarkInner2({
139
126
  (0, import_dom.markEventAsHandled)(e);
140
127
  (0, import_dom.preventDefault)(e);
141
128
  },
142
- title: "made with tldraw",
129
+ title: "Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev.",
143
130
  onClick: () => import_runtime.runtime.openWindow(url, "_blank"),
144
131
  style: { mask: maskCss, WebkitMask: maskCss }
145
132
  }
@@ -150,7 +137,8 @@ const WatermarkInner = (0, import_react.memo)(function WatermarkInner2({
150
137
  const LicenseStyles = (0, import_react.memo)(function LicenseStyles2() {
151
138
  const editor = (0, import_useEditor.useEditor)();
152
139
  const className = import_LicenseManager.LicenseManager.className;
153
- const CSS = `/* ------------------- SEE LICENSE -------------------
140
+ const CSS = `
141
+ /* ------------------- SEE LICENSE -------------------
154
142
  The tldraw watermark is part of tldraw's license. It is shown for unlicensed
155
143
  or "licensed-with-watermark" users. By using this library, you agree to
156
144
  preserve the watermark's behavior, keeping it visible, unobscured, and
@@ -159,87 +147,105 @@ available to user-interaction.
159
147
  To remove the watermark, please purchase a license at tldraw.dev.
160
148
  */
161
149
 
162
- .${className} {
163
- position: absolute;
164
- bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
165
- right: max(var(--tl-space-2), env(safe-area-inset-right));
166
- width: 96px;
167
- height: 32px;
168
- display: flex;
169
- align-items: center;
170
- justify-content: center;
171
- z-index: var(--tl-layer-watermark) !important;
172
- background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
173
- opacity: 1;
174
- border-radius: 5px;
175
- pointer-events: all;
176
- padding: 2px;
177
- box-sizing: content-box;
178
- }
150
+ .${className} {
151
+ position: absolute;
152
+ bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
153
+ right: max(var(--tl-space-2), env(safe-area-inset-right));
154
+ width: 96px;
155
+ height: 32px;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ z-index: var(--tl-layer-watermark) !important;
160
+ background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
161
+ opacity: 1;
162
+ border-radius: 5px;
163
+ pointer-events: all;
164
+ padding: 2px;
165
+ box-sizing: content-box;
166
+ }
179
167
 
180
- .${className} > button {
181
- position: absolute;
182
- width: 96px;
183
- height: 32px;
184
- pointer-events: all;
185
- cursor: inherit;
186
- color: var(--tl-color-text);
187
- opacity: .38;
188
- border: 0;
189
- padding: 0;
190
- background-color: currentColor;
191
- }
168
+ .${className} > button {
169
+ position: absolute;
170
+ width: 96px;
171
+ height: 32px;
172
+ pointer-events: all;
173
+ cursor: inherit;
174
+ color: var(--tl-color-text);
175
+ opacity: .38;
176
+ border: 0;
177
+ padding: 0;
178
+ background-color: currentColor;
179
+ }
192
180
 
193
- .${className}[data-debug='true'] {
194
- bottom: max(46px, env(safe-area-inset-bottom));
195
- }
181
+ .${className}[data-debug='true'] {
182
+ bottom: max(46px, env(safe-area-inset-bottom));
183
+ }
196
184
 
197
- .${className}[data-mobile='true'] {
198
- border-radius: 4px 0px 0px 4px;
199
- right: max(-2px, calc(env(safe-area-inset-right) - 2px));
200
- width: 8px;
201
- height: 48px;
202
- }
185
+ .${className}[data-mobile='true'] {
186
+ border-radius: 4px 0px 0px 4px;
187
+ right: max(-2px, calc(env(safe-area-inset-right) - 2px));
188
+ width: 8px;
189
+ height: 48px;
190
+ }
203
191
 
204
- .${className}[data-mobile='true'] > button {
205
- width: 8px;
206
- height: 32px;
207
- }
192
+ .${className}[data-mobile='true'] > button {
193
+ width: 8px;
194
+ height: 32px;
195
+ }
208
196
 
209
- @media (hover: hover) {
210
- .${className} > button {
211
- pointer-events: none;
212
- }
197
+ .${className}[data-unlicensed='true'] > button {
198
+ font-size: 100px;
199
+ position: absolute;
200
+ pointer-events: all;
201
+ cursor: pointer;
202
+ color: var(--tl-color-text);
203
+ opacity: 0.8;
204
+ border: 0;
205
+ padding: 0;
206
+ background-color: transparent;
207
+ font-size: 11px;
208
+ font-weight: 600;
209
+ text-align: center;
210
+ }
213
211
 
214
- .${className}:hover {
215
- background-color: var(--tl-color-background);
216
- transition: background-color 0.2s ease-in-out;
217
- transition-delay: 0.32s;
218
- }
212
+ .${className}[data-mobile='true'][data-unlicensed='true'] > button {
213
+ display: none;
214
+ }
219
215
 
220
- .${className}:hover > button {
221
- animation: ${className}_delayed_link 0.2s forwards ease-in-out;
222
- animation-delay: 0.32s;
223
- }
216
+ @media (hover: hover) {
217
+ .${className}[data-licensed='false'] > button {
218
+ pointer-events: none;
219
+ }
220
+
221
+ .${className}[data-licensed='false']:hover {
222
+ background-color: var(--tl-color-background);
223
+ transition: background-color 0.2s ease-in-out;
224
+ transition-delay: 0.32s;
225
+ }
224
226
 
225
- .${className} > button:focus-visible {
226
- opacity: 1;
227
- }
227
+ .${className}[data-licensed='false']:hover > button {
228
+ animation: ${className}_delayed_link 0.2s forwards ease-in-out;
229
+ animation-delay: 0.32s;
228
230
  }
229
231
 
232
+ .${className}[data-licensed='false'] > button:focus-visible {
233
+ opacity: 1;
234
+ }
235
+ }
230
236
 
231
- @keyframes ${className}_delayed_link {
232
- 0% {
233
- cursor: inherit;
234
- opacity: .38;
235
- pointer-events: none;
236
- }
237
- 100% {
238
- cursor: pointer;
239
- opacity: 1;
240
- pointer-events: all;
241
- }
242
- }`;
237
+ @keyframes ${className}_delayed_link {
238
+ 0% {
239
+ cursor: inherit;
240
+ opacity: .38;
241
+ pointer-events: none;
242
+ }
243
+ 100% {
244
+ cursor: pointer;
245
+ opacity: 1;
246
+ pointer-events: all;
247
+ }
248
+ }`;
243
249
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { nonce: editor.options.nonce, children: CSS });
244
250
  });
245
251
  //# sourceMappingURL=Watermark.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/license/Watermark.tsx"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'\nimport { markEventAsHandled, preventDefault } from '../utils/dom'\nimport { runtime } from '../utils/runtime'\nimport { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'\nimport { LicenseManager } from './LicenseManager'\nimport { useLicenseContext } from './LicenseProvider'\nimport { useLicenseManagerState } from './useLicenseManagerState'\n\nconst WATERMARK_DESKTOP_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkDesktopSvg)}`\nconst WATERMARK_MOBILE_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkMobileSvg)}`\n\n/** @internal */\nexport const Watermark = memo(function Watermark() {\n\tconst licenseManager = useLicenseContext()\n\tconst editor = useEditor()\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\n\tconst licenseManagerState = useLicenseManagerState(licenseManager)\n\n\tif (!['licensed-with-watermark', 'unlicensed'].includes(licenseManagerState)) return null\n\n\treturn (\n\t\t<>\n\t\t\t<LicenseStyles />\n\t\t\t<WatermarkInner\n\t\t\t\tsrc={isMobile ? WATERMARK_MOBILE_LOCAL_SRC : WATERMARK_DESKTOP_LOCAL_SRC}\n\t\t\t\tisUnlicensed={licenseManagerState === 'unlicensed'}\n\t\t\t/>\n\t\t</>\n\t)\n})\n\nconst UnlicensedWatermark = memo(function UnlicensedWatermark({\n\tisDebugMode,\n\tisMobile,\n}: {\n\tisDebugMode: boolean\n\tisMobile: boolean\n}) {\n\tconst events = useCanvasEvents()\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-unlicensed={true}\n\t\t\tdata-testid=\"tl-watermark-unlicensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"Unlicensed - click to get a license\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\tpointerEvents: 'all',\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\tcolor: 'var(--tl-color-text)',\n\t\t\t\t\topacity: 0.8,\n\t\t\t\t\tborder: 0,\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\tfontSize: '11px',\n\t\t\t\t\tfontWeight: '600',\n\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\tUnlicensed\n\t\t\t</button>\n\t\t</div>\n\t)\n})\n\nconst WatermarkInner = memo(function WatermarkInner({\n\tsrc,\n\tisUnlicensed,\n}: {\n\tsrc: string\n\tisUnlicensed: boolean\n}) {\n\tconst editor = useEditor()\n\tconst isDebugMode = useValue('debug mode', () => editor.getInstanceState().isDebugMode, [editor])\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\tconst events = useCanvasEvents()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst maskCss = `url('${src}') center 100% / 100% no-repeat`\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\tif (isUnlicensed) {\n\t\treturn <UnlicensedWatermark isDebugMode={isDebugMode} isMobile={isMobile} />\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-testid=\"tl-watermark-licensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"made with tldraw\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{ mask: maskCss, WebkitMask: maskCss }}\n\t\t\t/>\n\t\t</div>\n\t)\n})\n\nconst LicenseStyles = memo(function LicenseStyles() {\n\tconst editor = useEditor()\n\tconst className = LicenseManager.className\n\n\tconst CSS = `/* ------------------- SEE LICENSE -------------------\nThe tldraw watermark is part of tldraw's license. It is shown for unlicensed\nor \"licensed-with-watermark\" users. By using this library, you agree to\npreserve the watermark's behavior, keeping it visible, unobscured, and\navailable to user-interaction.\n\nTo remove the watermark, please purchase a license at tldraw.dev.\n*/\n\n\t.${className} {\n\t\tposition: absolute;\n\t\tbottom: max(var(--tl-space-2), env(safe-area-inset-bottom));\n\t\tright: max(var(--tl-space-2), env(safe-area-inset-right));\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tz-index: var(--tl-layer-watermark) !important;\n\t\tbackground-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);\n\t\topacity: 1;\n\t\tborder-radius: 5px;\n\t\tpointer-events: all;\n\t\tpadding: 2px;\n\t\tbox-sizing: content-box;\n\t}\n\n\t.${className} > button {\n\t\tposition: absolute;\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tpointer-events: all;\n\t\tcursor: inherit;\n\t\tcolor: var(--tl-color-text);\n\t\topacity: .38;\n\t\tborder: 0;\n\t\tpadding: 0;\n\t\tbackground-color: currentColor;\n\t}\n\n\t.${className}[data-debug='true'] {\n\t\tbottom: max(46px, env(safe-area-inset-bottom));\n\t}\n\n\t.${className}[data-mobile='true'] {\n\t\tborder-radius: 4px 0px 0px 4px;\n\t\tright: max(-2px, calc(env(safe-area-inset-right) - 2px));\n\t\twidth: 8px;\n\t\theight: 48px;\n\t}\n\n\t.${className}[data-mobile='true'] > button {\n\t\twidth: 8px;\n\t\theight: 32px;\n\t}\n\n\t@media (hover: hover) {\n\t\t.${className} > button {\n\t\t\tpointer-events: none;\n\t\t}\n\n\t\t.${className}:hover {\n\t\t\tbackground-color: var(--tl-color-background);\n\t\t\ttransition: background-color 0.2s ease-in-out;\n\t\t\ttransition-delay: 0.32s;\n\t\t}\n\n\t\t.${className}:hover > button {\n\t\t\tanimation: ${className}_delayed_link 0.2s forwards ease-in-out;\n\t\t\tanimation-delay: 0.32s;\n\t\t}\n\n\t\t.${className} > button:focus-visible {\n\t\t\topacity: 1;\n\t\t}\n\t}\n\n\n\t@keyframes ${className}_delayed_link {\n\t\t0% {\n\t\t\tcursor: inherit;\n\t\t\topacity: .38;\n\t\t\tpointer-events: none;\n\t\t}\n\t\t100% {\n\t\t\tcursor: pointer;\n\t\t\topacity: 1;\n\t\t\tpointer-events: all;\n\t\t}\n\t}`\n\n\treturn <style nonce={editor.options.nonce}>{CSS}</style>\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'\nimport { markEventAsHandled, preventDefault } from '../utils/dom'\nimport { runtime } from '../utils/runtime'\nimport { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'\nimport { LicenseManager } from './LicenseManager'\nimport { useLicenseContext } from './LicenseProvider'\nimport { useLicenseManagerState } from './useLicenseManagerState'\n\nconst WATERMARK_DESKTOP_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkDesktopSvg)}`\nconst WATERMARK_MOBILE_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkMobileSvg)}`\n\n/** @internal */\nexport const Watermark = memo(function Watermark() {\n\tconst licenseManager = useLicenseContext()\n\tconst editor = useEditor()\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\n\tconst licenseManagerState = useLicenseManagerState(licenseManager)\n\n\tif (!['licensed-with-watermark', 'unlicensed'].includes(licenseManagerState)) return null\n\n\treturn (\n\t\t<>\n\t\t\t<LicenseStyles />\n\t\t\t<WatermarkInner\n\t\t\t\tsrc={isMobile ? WATERMARK_MOBILE_LOCAL_SRC : WATERMARK_DESKTOP_LOCAL_SRC}\n\t\t\t\tisUnlicensed={licenseManagerState === 'unlicensed'}\n\t\t\t/>\n\t\t</>\n\t)\n})\n\nconst UnlicensedWatermark = memo(function UnlicensedWatermark({\n\tisDebugMode,\n\tisMobile,\n}: {\n\tisDebugMode: boolean\n\tisMobile: boolean\n}) {\n\tconst events = useCanvasEvents()\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst url =\n\t\t'https://tldraw.dev/pricing?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-unlicensed={true}\n\t\t\tdata-testid=\"tl-watermark-unlicensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing.\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t>\n\t\t\t\tGet a license for production\n\t\t\t</button>\n\t\t</div>\n\t)\n})\n\nconst WatermarkInner = memo(function WatermarkInner({\n\tsrc,\n\tisUnlicensed,\n}: {\n\tsrc: string\n\tisUnlicensed: boolean\n}) {\n\tconst editor = useEditor()\n\tconst isDebugMode = useValue('debug mode', () => editor.getInstanceState().isDebugMode, [editor])\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\tconst events = useCanvasEvents()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst maskCss = `url('${src}') center 100% / 100% no-repeat`\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\tif (isUnlicensed) {\n\t\treturn <UnlicensedWatermark isDebugMode={isDebugMode} isMobile={isMobile} />\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-testid=\"tl-watermark-licensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev.\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{ mask: maskCss, WebkitMask: maskCss }}\n\t\t\t/>\n\t\t</div>\n\t)\n})\n\nconst LicenseStyles = memo(function LicenseStyles() {\n\tconst editor = useEditor()\n\tconst className = LicenseManager.className\n\n\tconst CSS = `\n/* ------------------- SEE LICENSE -------------------\nThe tldraw watermark is part of tldraw's license. It is shown for unlicensed\nor \"licensed-with-watermark\" users. By using this library, you agree to\npreserve the watermark's behavior, keeping it visible, unobscured, and\navailable to user-interaction.\n\nTo remove the watermark, please purchase a license at tldraw.dev.\n*/\n\n.${className} {\n\tposition: absolute;\n\tbottom: max(var(--tl-space-2), env(safe-area-inset-bottom));\n\tright: max(var(--tl-space-2), env(safe-area-inset-right));\n\twidth: 96px;\n\theight: 32px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tz-index: var(--tl-layer-watermark) !important;\n\tbackground-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);\n\topacity: 1;\n\tborder-radius: 5px;\n\tpointer-events: all;\n\tpadding: 2px;\n\tbox-sizing: content-box;\n}\n\n.${className} > button {\n\tposition: absolute;\n\twidth: 96px;\n\theight: 32px;\n\tpointer-events: all;\n\tcursor: inherit;\n\tcolor: var(--tl-color-text);\n\topacity: .38;\n\tborder: 0;\n\tpadding: 0;\n\tbackground-color: currentColor;\n}\n\n.${className}[data-debug='true'] {\n\tbottom: max(46px, env(safe-area-inset-bottom));\n}\n\n.${className}[data-mobile='true'] {\n\tborder-radius: 4px 0px 0px 4px;\n\tright: max(-2px, calc(env(safe-area-inset-right) - 2px));\n\twidth: 8px;\n\theight: 48px;\n}\n\n.${className}[data-mobile='true'] > button {\n\twidth: 8px;\n\theight: 32px;\n}\n\n.${className}[data-unlicensed='true'] > button {\n\tfont-size: 100px;\n\tposition: absolute;\n\tpointer-events: all;\n\tcursor: pointer;\n\tcolor: var(--tl-color-text);\n\topacity: 0.8;\n\tborder: 0;\n\tpadding: 0;\n\tbackground-color: transparent;\n\tfont-size: 11px;\n\tfont-weight: 600;\n\ttext-align: center;\n}\n\n.${className}[data-mobile='true'][data-unlicensed='true'] > button {\n\tdisplay: none;\n}\n\n@media (hover: hover) {\n\t.${className}[data-licensed='false'] > button {\n\t\tpointer-events: none;\n\t}\n\n\t.${className}[data-licensed='false']:hover {\n\t\tbackground-color: var(--tl-color-background);\n\t\ttransition: background-color 0.2s ease-in-out;\n\t\ttransition-delay: 0.32s;\n\t}\n\n\t.${className}[data-licensed='false']:hover > button {\n\t\tanimation: ${className}_delayed_link 0.2s forwards ease-in-out;\n\t\tanimation-delay: 0.32s;\n\t}\n\n\t.${className}[data-licensed='false'] > button:focus-visible {\n\t\topacity: 1;\n\t}\n}\n\n@keyframes ${className}_delayed_link {\n\t0% {\n\t\tcursor: inherit;\n\t\topacity: .38;\n\t\tpointer-events: none;\n\t}\n\t100% {\n\t\tcursor: pointer;\n\t\topacity: 1;\n\t\tpointer-events: all;\n\t}\n}`\n\n\treturn <style nonce={editor.options.nonce}>{CSS}</style>\n})\n"],
5
+ "mappings": "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",
6
6
  "names": ["Watermark", "UnlicensedWatermark", "WatermarkInner", "LicenseStyles"]
7
7
  }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "3.16.0-canary.ba3bc37d4418";
25
+ const version = "3.16.0-canary.bf7be9dad88b";
26
26
  const publishDates = {
27
27
  major: "2024-09-13T14:36:29.063Z",
28
- minor: "2025-09-16T14:55:49.384Z",
29
- patch: "2025-09-16T14:55:49.384Z"
28
+ minor: "2025-09-17T15:01:00.589Z",
29
+ patch: "2025-09-17T15:01:00.589Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.ba3bc37d4418'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-16T14:55:49.384Z',\n\tpatch: '2025-09-16T14:55:49.384Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.bf7be9dad88b'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-17T15:01:00.589Z',\n\tpatch: '2025-09-17T15:01:00.589Z',\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -303,7 +303,7 @@ import { uniq } from "./lib/utils/uniq.mjs";
303
303
  import { openWindow } from "./lib/utils/window-open.mjs";
304
304
  registerTldrawLibraryVersion(
305
305
  "@tldraw/editor",
306
- "3.16.0-canary.ba3bc37d4418",
306
+ "3.16.0-canary.bf7be9dad88b",
307
307
  "esm"
308
308
  );
309
309
  export {
@@ -39,8 +39,10 @@ class FocusManager {
39
39
  }
40
40
  handleKeyDown(keyEvent) {
41
41
  const container = this.editor.getContainer();
42
- if (this.editor.isIn("select.editing_shape")) return;
43
- if (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return;
42
+ const activeEl = document.activeElement;
43
+ if (this.editor.isIn("select.editing_shape") && !activeEl?.closest(".tlui-contextual-toolbar"))
44
+ return;
45
+ if (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return;
44
46
  if (["Tab", "ArrowUp", "ArrowDown"].includes(keyEvent.key)) {
45
47
  container.classList.remove("tl-container__no-focus-ring");
46
48
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/managers/FocusManager/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\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 (this.editor.isIn('select.editing_shape')) return\n\t\tif (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return\n\t\tif (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {\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,KAAK,OAAO,KAAK,sBAAsB,EAAG;AAC9C,QAAI,SAAS,kBAAkB,aAAa,KAAK,OAAO,oBAAoB,EAAE,SAAS,EAAG;AAC1F,QAAI,CAAC,OAAO,WAAW,WAAW,EAAE,SAAS,SAAS,GAAG,GAAG;AAC3D,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;",
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\tconst activeEl = document.activeElement\n\t\t// Edit mode should remove the focus ring, however if the active element's\n\t\t// parent is the contextual toolbar, then allow it.\n\t\tif (this.editor.isIn('select.editing_shape') && !activeEl?.closest('.tlui-contextual-toolbar'))\n\t\t\treturn\n\t\tif (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return\n\t\tif (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {\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,UAAM,WAAW,SAAS;AAG1B,QAAI,KAAK,OAAO,KAAK,sBAAsB,KAAK,CAAC,UAAU,QAAQ,0BAA0B;AAC5F;AACD,QAAI,aAAa,aAAa,KAAK,OAAO,oBAAoB,EAAE,SAAS,EAAG;AAC5E,QAAI,CAAC,OAAO,WAAW,WAAW,EAAE,SAAS,SAAS,GAAG,GAAG;AAC3D,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
  }
@@ -38,7 +38,7 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark2({
38
38
  const events = useCanvasEvents();
39
39
  const ref = useRef(null);
40
40
  usePassThroughWheelEvents(ref);
41
- const url = "https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark";
41
+ const url = "https://tldraw.dev/pricing?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark";
42
42
  return /* @__PURE__ */ jsx(
43
43
  "div",
44
44
  {
@@ -59,22 +59,9 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark2({
59
59
  markEventAsHandled(e);
60
60
  preventDefault(e);
61
61
  },
62
- title: "Unlicensed - click to get a license",
62
+ title: "The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing.",
63
63
  onClick: () => runtime.openWindow(url, "_blank"),
64
- style: {
65
- position: "absolute",
66
- pointerEvents: "all",
67
- cursor: "pointer",
68
- color: "var(--tl-color-text)",
69
- opacity: 0.8,
70
- border: 0,
71
- padding: 0,
72
- backgroundColor: "transparent",
73
- fontSize: "11px",
74
- fontWeight: "600",
75
- textAlign: "center"
76
- },
77
- children: "Unlicensed"
64
+ children: "Get a license for production"
78
65
  }
79
66
  )
80
67
  }
@@ -116,7 +103,7 @@ const WatermarkInner = memo(function WatermarkInner2({
116
103
  markEventAsHandled(e);
117
104
  preventDefault(e);
118
105
  },
119
- title: "made with tldraw",
106
+ title: "Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev.",
120
107
  onClick: () => runtime.openWindow(url, "_blank"),
121
108
  style: { mask: maskCss, WebkitMask: maskCss }
122
109
  }
@@ -127,7 +114,8 @@ const WatermarkInner = memo(function WatermarkInner2({
127
114
  const LicenseStyles = memo(function LicenseStyles2() {
128
115
  const editor = useEditor();
129
116
  const className = LicenseManager.className;
130
- const CSS = `/* ------------------- SEE LICENSE -------------------
117
+ const CSS = `
118
+ /* ------------------- SEE LICENSE -------------------
131
119
  The tldraw watermark is part of tldraw's license. It is shown for unlicensed
132
120
  or "licensed-with-watermark" users. By using this library, you agree to
133
121
  preserve the watermark's behavior, keeping it visible, unobscured, and
@@ -136,87 +124,105 @@ available to user-interaction.
136
124
  To remove the watermark, please purchase a license at tldraw.dev.
137
125
  */
138
126
 
139
- .${className} {
140
- position: absolute;
141
- bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
142
- right: max(var(--tl-space-2), env(safe-area-inset-right));
143
- width: 96px;
144
- height: 32px;
145
- display: flex;
146
- align-items: center;
147
- justify-content: center;
148
- z-index: var(--tl-layer-watermark) !important;
149
- background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
150
- opacity: 1;
151
- border-radius: 5px;
152
- pointer-events: all;
153
- padding: 2px;
154
- box-sizing: content-box;
155
- }
127
+ .${className} {
128
+ position: absolute;
129
+ bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
130
+ right: max(var(--tl-space-2), env(safe-area-inset-right));
131
+ width: 96px;
132
+ height: 32px;
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ z-index: var(--tl-layer-watermark) !important;
137
+ background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
138
+ opacity: 1;
139
+ border-radius: 5px;
140
+ pointer-events: all;
141
+ padding: 2px;
142
+ box-sizing: content-box;
143
+ }
156
144
 
157
- .${className} > button {
158
- position: absolute;
159
- width: 96px;
160
- height: 32px;
161
- pointer-events: all;
162
- cursor: inherit;
163
- color: var(--tl-color-text);
164
- opacity: .38;
165
- border: 0;
166
- padding: 0;
167
- background-color: currentColor;
168
- }
145
+ .${className} > button {
146
+ position: absolute;
147
+ width: 96px;
148
+ height: 32px;
149
+ pointer-events: all;
150
+ cursor: inherit;
151
+ color: var(--tl-color-text);
152
+ opacity: .38;
153
+ border: 0;
154
+ padding: 0;
155
+ background-color: currentColor;
156
+ }
169
157
 
170
- .${className}[data-debug='true'] {
171
- bottom: max(46px, env(safe-area-inset-bottom));
172
- }
158
+ .${className}[data-debug='true'] {
159
+ bottom: max(46px, env(safe-area-inset-bottom));
160
+ }
173
161
 
174
- .${className}[data-mobile='true'] {
175
- border-radius: 4px 0px 0px 4px;
176
- right: max(-2px, calc(env(safe-area-inset-right) - 2px));
177
- width: 8px;
178
- height: 48px;
179
- }
162
+ .${className}[data-mobile='true'] {
163
+ border-radius: 4px 0px 0px 4px;
164
+ right: max(-2px, calc(env(safe-area-inset-right) - 2px));
165
+ width: 8px;
166
+ height: 48px;
167
+ }
180
168
 
181
- .${className}[data-mobile='true'] > button {
182
- width: 8px;
183
- height: 32px;
184
- }
169
+ .${className}[data-mobile='true'] > button {
170
+ width: 8px;
171
+ height: 32px;
172
+ }
185
173
 
186
- @media (hover: hover) {
187
- .${className} > button {
188
- pointer-events: none;
189
- }
174
+ .${className}[data-unlicensed='true'] > button {
175
+ font-size: 100px;
176
+ position: absolute;
177
+ pointer-events: all;
178
+ cursor: pointer;
179
+ color: var(--tl-color-text);
180
+ opacity: 0.8;
181
+ border: 0;
182
+ padding: 0;
183
+ background-color: transparent;
184
+ font-size: 11px;
185
+ font-weight: 600;
186
+ text-align: center;
187
+ }
190
188
 
191
- .${className}:hover {
192
- background-color: var(--tl-color-background);
193
- transition: background-color 0.2s ease-in-out;
194
- transition-delay: 0.32s;
195
- }
189
+ .${className}[data-mobile='true'][data-unlicensed='true'] > button {
190
+ display: none;
191
+ }
196
192
 
197
- .${className}:hover > button {
198
- animation: ${className}_delayed_link 0.2s forwards ease-in-out;
199
- animation-delay: 0.32s;
200
- }
193
+ @media (hover: hover) {
194
+ .${className}[data-licensed='false'] > button {
195
+ pointer-events: none;
196
+ }
197
+
198
+ .${className}[data-licensed='false']:hover {
199
+ background-color: var(--tl-color-background);
200
+ transition: background-color 0.2s ease-in-out;
201
+ transition-delay: 0.32s;
202
+ }
201
203
 
202
- .${className} > button:focus-visible {
203
- opacity: 1;
204
- }
204
+ .${className}[data-licensed='false']:hover > button {
205
+ animation: ${className}_delayed_link 0.2s forwards ease-in-out;
206
+ animation-delay: 0.32s;
205
207
  }
206
208
 
209
+ .${className}[data-licensed='false'] > button:focus-visible {
210
+ opacity: 1;
211
+ }
212
+ }
207
213
 
208
- @keyframes ${className}_delayed_link {
209
- 0% {
210
- cursor: inherit;
211
- opacity: .38;
212
- pointer-events: none;
213
- }
214
- 100% {
215
- cursor: pointer;
216
- opacity: 1;
217
- pointer-events: all;
218
- }
219
- }`;
214
+ @keyframes ${className}_delayed_link {
215
+ 0% {
216
+ cursor: inherit;
217
+ opacity: .38;
218
+ pointer-events: none;
219
+ }
220
+ 100% {
221
+ cursor: pointer;
222
+ opacity: 1;
223
+ pointer-events: all;
224
+ }
225
+ }`;
220
226
  return /* @__PURE__ */ jsx("style", { nonce: editor.options.nonce, children: CSS });
221
227
  });
222
228
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/license/Watermark.tsx"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'\nimport { markEventAsHandled, preventDefault } from '../utils/dom'\nimport { runtime } from '../utils/runtime'\nimport { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'\nimport { LicenseManager } from './LicenseManager'\nimport { useLicenseContext } from './LicenseProvider'\nimport { useLicenseManagerState } from './useLicenseManagerState'\n\nconst WATERMARK_DESKTOP_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkDesktopSvg)}`\nconst WATERMARK_MOBILE_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkMobileSvg)}`\n\n/** @internal */\nexport const Watermark = memo(function Watermark() {\n\tconst licenseManager = useLicenseContext()\n\tconst editor = useEditor()\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\n\tconst licenseManagerState = useLicenseManagerState(licenseManager)\n\n\tif (!['licensed-with-watermark', 'unlicensed'].includes(licenseManagerState)) return null\n\n\treturn (\n\t\t<>\n\t\t\t<LicenseStyles />\n\t\t\t<WatermarkInner\n\t\t\t\tsrc={isMobile ? WATERMARK_MOBILE_LOCAL_SRC : WATERMARK_DESKTOP_LOCAL_SRC}\n\t\t\t\tisUnlicensed={licenseManagerState === 'unlicensed'}\n\t\t\t/>\n\t\t</>\n\t)\n})\n\nconst UnlicensedWatermark = memo(function UnlicensedWatermark({\n\tisDebugMode,\n\tisMobile,\n}: {\n\tisDebugMode: boolean\n\tisMobile: boolean\n}) {\n\tconst events = useCanvasEvents()\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-unlicensed={true}\n\t\t\tdata-testid=\"tl-watermark-unlicensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"Unlicensed - click to get a license\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\tpointerEvents: 'all',\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\tcolor: 'var(--tl-color-text)',\n\t\t\t\t\topacity: 0.8,\n\t\t\t\t\tborder: 0,\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\tfontSize: '11px',\n\t\t\t\t\tfontWeight: '600',\n\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\tUnlicensed\n\t\t\t</button>\n\t\t</div>\n\t)\n})\n\nconst WatermarkInner = memo(function WatermarkInner({\n\tsrc,\n\tisUnlicensed,\n}: {\n\tsrc: string\n\tisUnlicensed: boolean\n}) {\n\tconst editor = useEditor()\n\tconst isDebugMode = useValue('debug mode', () => editor.getInstanceState().isDebugMode, [editor])\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\tconst events = useCanvasEvents()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst maskCss = `url('${src}') center 100% / 100% no-repeat`\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\tif (isUnlicensed) {\n\t\treturn <UnlicensedWatermark isDebugMode={isDebugMode} isMobile={isMobile} />\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-testid=\"tl-watermark-licensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"made with tldraw\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{ mask: maskCss, WebkitMask: maskCss }}\n\t\t\t/>\n\t\t</div>\n\t)\n})\n\nconst LicenseStyles = memo(function LicenseStyles() {\n\tconst editor = useEditor()\n\tconst className = LicenseManager.className\n\n\tconst CSS = `/* ------------------- SEE LICENSE -------------------\nThe tldraw watermark is part of tldraw's license. It is shown for unlicensed\nor \"licensed-with-watermark\" users. By using this library, you agree to\npreserve the watermark's behavior, keeping it visible, unobscured, and\navailable to user-interaction.\n\nTo remove the watermark, please purchase a license at tldraw.dev.\n*/\n\n\t.${className} {\n\t\tposition: absolute;\n\t\tbottom: max(var(--tl-space-2), env(safe-area-inset-bottom));\n\t\tright: max(var(--tl-space-2), env(safe-area-inset-right));\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tz-index: var(--tl-layer-watermark) !important;\n\t\tbackground-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);\n\t\topacity: 1;\n\t\tborder-radius: 5px;\n\t\tpointer-events: all;\n\t\tpadding: 2px;\n\t\tbox-sizing: content-box;\n\t}\n\n\t.${className} > button {\n\t\tposition: absolute;\n\t\twidth: 96px;\n\t\theight: 32px;\n\t\tpointer-events: all;\n\t\tcursor: inherit;\n\t\tcolor: var(--tl-color-text);\n\t\topacity: .38;\n\t\tborder: 0;\n\t\tpadding: 0;\n\t\tbackground-color: currentColor;\n\t}\n\n\t.${className}[data-debug='true'] {\n\t\tbottom: max(46px, env(safe-area-inset-bottom));\n\t}\n\n\t.${className}[data-mobile='true'] {\n\t\tborder-radius: 4px 0px 0px 4px;\n\t\tright: max(-2px, calc(env(safe-area-inset-right) - 2px));\n\t\twidth: 8px;\n\t\theight: 48px;\n\t}\n\n\t.${className}[data-mobile='true'] > button {\n\t\twidth: 8px;\n\t\theight: 32px;\n\t}\n\n\t@media (hover: hover) {\n\t\t.${className} > button {\n\t\t\tpointer-events: none;\n\t\t}\n\n\t\t.${className}:hover {\n\t\t\tbackground-color: var(--tl-color-background);\n\t\t\ttransition: background-color 0.2s ease-in-out;\n\t\t\ttransition-delay: 0.32s;\n\t\t}\n\n\t\t.${className}:hover > button {\n\t\t\tanimation: ${className}_delayed_link 0.2s forwards ease-in-out;\n\t\t\tanimation-delay: 0.32s;\n\t\t}\n\n\t\t.${className} > button:focus-visible {\n\t\t\topacity: 1;\n\t\t}\n\t}\n\n\n\t@keyframes ${className}_delayed_link {\n\t\t0% {\n\t\t\tcursor: inherit;\n\t\t\topacity: .38;\n\t\t\tpointer-events: none;\n\t\t}\n\t\t100% {\n\t\t\tcursor: pointer;\n\t\t\topacity: 1;\n\t\t\tpointer-events: all;\n\t\t}\n\t}`\n\n\treturn <style nonce={editor.options.nonce}>{CSS}</style>\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { memo, useRef } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePassThroughWheelEvents } from '../hooks/usePassThroughWheelEvents'\nimport { markEventAsHandled, preventDefault } from '../utils/dom'\nimport { runtime } from '../utils/runtime'\nimport { watermarkDesktopSvg, watermarkMobileSvg } from '../watermarks'\nimport { LicenseManager } from './LicenseManager'\nimport { useLicenseContext } from './LicenseProvider'\nimport { useLicenseManagerState } from './useLicenseManagerState'\n\nconst WATERMARK_DESKTOP_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkDesktopSvg)}`\nconst WATERMARK_MOBILE_LOCAL_SRC = `data:image/svg+xml;utf8,${encodeURIComponent(watermarkMobileSvg)}`\n\n/** @internal */\nexport const Watermark = memo(function Watermark() {\n\tconst licenseManager = useLicenseContext()\n\tconst editor = useEditor()\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\n\tconst licenseManagerState = useLicenseManagerState(licenseManager)\n\n\tif (!['licensed-with-watermark', 'unlicensed'].includes(licenseManagerState)) return null\n\n\treturn (\n\t\t<>\n\t\t\t<LicenseStyles />\n\t\t\t<WatermarkInner\n\t\t\t\tsrc={isMobile ? WATERMARK_MOBILE_LOCAL_SRC : WATERMARK_DESKTOP_LOCAL_SRC}\n\t\t\t\tisUnlicensed={licenseManagerState === 'unlicensed'}\n\t\t\t/>\n\t\t</>\n\t)\n})\n\nconst UnlicensedWatermark = memo(function UnlicensedWatermark({\n\tisDebugMode,\n\tisMobile,\n}: {\n\tisDebugMode: boolean\n\tisMobile: boolean\n}) {\n\tconst events = useCanvasEvents()\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst url =\n\t\t'https://tldraw.dev/pricing?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-unlicensed={true}\n\t\t\tdata-testid=\"tl-watermark-unlicensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing.\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t>\n\t\t\t\tGet a license for production\n\t\t\t</button>\n\t\t</div>\n\t)\n})\n\nconst WatermarkInner = memo(function WatermarkInner({\n\tsrc,\n\tisUnlicensed,\n}: {\n\tsrc: string\n\tisUnlicensed: boolean\n}) {\n\tconst editor = useEditor()\n\tconst isDebugMode = useValue('debug mode', () => editor.getInstanceState().isDebugMode, [editor])\n\tconst isMobile = useValue('is mobile', () => editor.getViewportScreenBounds().width < 700, [\n\t\teditor,\n\t])\n\tconst events = useCanvasEvents()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst maskCss = `url('${src}') center 100% / 100% no-repeat`\n\tconst url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'\n\n\tif (isUnlicensed) {\n\t\treturn <UnlicensedWatermark isDebugMode={isDebugMode} isMobile={isMobile} />\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={LicenseManager.className}\n\t\t\tdata-debug={isDebugMode}\n\t\t\tdata-mobile={isMobile}\n\t\t\tdata-testid=\"tl-watermark-licensed\"\n\t\t\tdraggable={false}\n\t\t\t{...events}\n\t\t>\n\t\t\t<button\n\t\t\t\tdraggable={false}\n\t\t\t\trole=\"button\"\n\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}}\n\t\t\t\ttitle=\"Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev.\"\n\t\t\t\tonClick={() => runtime.openWindow(url, '_blank')}\n\t\t\t\tstyle={{ mask: maskCss, WebkitMask: maskCss }}\n\t\t\t/>\n\t\t</div>\n\t)\n})\n\nconst LicenseStyles = memo(function LicenseStyles() {\n\tconst editor = useEditor()\n\tconst className = LicenseManager.className\n\n\tconst CSS = `\n/* ------------------- SEE LICENSE -------------------\nThe tldraw watermark is part of tldraw's license. It is shown for unlicensed\nor \"licensed-with-watermark\" users. By using this library, you agree to\npreserve the watermark's behavior, keeping it visible, unobscured, and\navailable to user-interaction.\n\nTo remove the watermark, please purchase a license at tldraw.dev.\n*/\n\n.${className} {\n\tposition: absolute;\n\tbottom: max(var(--tl-space-2), env(safe-area-inset-bottom));\n\tright: max(var(--tl-space-2), env(safe-area-inset-right));\n\twidth: 96px;\n\theight: 32px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tz-index: var(--tl-layer-watermark) !important;\n\tbackground-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);\n\topacity: 1;\n\tborder-radius: 5px;\n\tpointer-events: all;\n\tpadding: 2px;\n\tbox-sizing: content-box;\n}\n\n.${className} > button {\n\tposition: absolute;\n\twidth: 96px;\n\theight: 32px;\n\tpointer-events: all;\n\tcursor: inherit;\n\tcolor: var(--tl-color-text);\n\topacity: .38;\n\tborder: 0;\n\tpadding: 0;\n\tbackground-color: currentColor;\n}\n\n.${className}[data-debug='true'] {\n\tbottom: max(46px, env(safe-area-inset-bottom));\n}\n\n.${className}[data-mobile='true'] {\n\tborder-radius: 4px 0px 0px 4px;\n\tright: max(-2px, calc(env(safe-area-inset-right) - 2px));\n\twidth: 8px;\n\theight: 48px;\n}\n\n.${className}[data-mobile='true'] > button {\n\twidth: 8px;\n\theight: 32px;\n}\n\n.${className}[data-unlicensed='true'] > button {\n\tfont-size: 100px;\n\tposition: absolute;\n\tpointer-events: all;\n\tcursor: pointer;\n\tcolor: var(--tl-color-text);\n\topacity: 0.8;\n\tborder: 0;\n\tpadding: 0;\n\tbackground-color: transparent;\n\tfont-size: 11px;\n\tfont-weight: 600;\n\ttext-align: center;\n}\n\n.${className}[data-mobile='true'][data-unlicensed='true'] > button {\n\tdisplay: none;\n}\n\n@media (hover: hover) {\n\t.${className}[data-licensed='false'] > button {\n\t\tpointer-events: none;\n\t}\n\n\t.${className}[data-licensed='false']:hover {\n\t\tbackground-color: var(--tl-color-background);\n\t\ttransition: background-color 0.2s ease-in-out;\n\t\ttransition-delay: 0.32s;\n\t}\n\n\t.${className}[data-licensed='false']:hover > button {\n\t\tanimation: ${className}_delayed_link 0.2s forwards ease-in-out;\n\t\tanimation-delay: 0.32s;\n\t}\n\n\t.${className}[data-licensed='false'] > button:focus-visible {\n\t\topacity: 1;\n\t}\n}\n\n@keyframes ${className}_delayed_link {\n\t0% {\n\t\tcursor: inherit;\n\t\topacity: .38;\n\t\tpointer-events: none;\n\t}\n\t100% {\n\t\tcursor: pointer;\n\t\topacity: 1;\n\t\tpointer-events: all;\n\t}\n}`\n\n\treturn <style nonce={editor.options.nonce}>{CSS}</style>\n})\n"],
5
+ "mappings": "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",
6
6
  "names": ["Watermark", "UnlicensedWatermark", "WatermarkInner", "LicenseStyles"]
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.16.0-canary.ba3bc37d4418";
1
+ const version = "3.16.0-canary.bf7be9dad88b";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-09-16T14:55:49.384Z",
5
- patch: "2025-09-16T14:55:49.384Z"
4
+ minor: "2025-09-17T15:01:00.589Z",
5
+ patch: "2025-09-17T15:01:00.589Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.ba3bc37d4418'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-16T14:55:49.384Z',\n\tpatch: '2025-09-16T14:55:49.384Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.bf7be9dad88b'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-17T15:01:00.589Z',\n\tpatch: '2025-09-17T15:01:00.589Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/editor",
3
3
  "description": "tldraw infinite canvas SDK (editor).",
4
- "version": "3.16.0-canary.ba3bc37d4418",
4
+ "version": "3.16.0-canary.bf7be9dad88b",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -50,12 +50,12 @@
50
50
  "@tiptap/core": "^2.9.1",
51
51
  "@tiptap/pm": "^2.9.1",
52
52
  "@tiptap/react": "^2.9.1",
53
- "@tldraw/state": "3.16.0-canary.ba3bc37d4418",
54
- "@tldraw/state-react": "3.16.0-canary.ba3bc37d4418",
55
- "@tldraw/store": "3.16.0-canary.ba3bc37d4418",
56
- "@tldraw/tlschema": "3.16.0-canary.ba3bc37d4418",
57
- "@tldraw/utils": "3.16.0-canary.ba3bc37d4418",
58
- "@tldraw/validate": "3.16.0-canary.ba3bc37d4418",
53
+ "@tldraw/state": "3.16.0-canary.bf7be9dad88b",
54
+ "@tldraw/state-react": "3.16.0-canary.bf7be9dad88b",
55
+ "@tldraw/store": "3.16.0-canary.bf7be9dad88b",
56
+ "@tldraw/tlschema": "3.16.0-canary.bf7be9dad88b",
57
+ "@tldraw/utils": "3.16.0-canary.bf7be9dad88b",
58
+ "@tldraw/validate": "3.16.0-canary.bf7be9dad88b",
59
59
  "@types/core-js": "^2.5.8",
60
60
  "@use-gesture/react": "^10.3.1",
61
61
  "classnames": "^2.5.1",
@@ -58,8 +58,12 @@ export class FocusManager {
58
58
 
59
59
  private handleKeyDown(keyEvent: KeyboardEvent) {
60
60
  const container = this.editor.getContainer()
61
- if (this.editor.isIn('select.editing_shape')) return
62
- if (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return
61
+ const activeEl = document.activeElement
62
+ // Edit mode should remove the focus ring, however if the active element's
63
+ // parent is the contextual toolbar, then allow it.
64
+ if (this.editor.isIn('select.editing_shape') && !activeEl?.closest('.tlui-contextual-toolbar'))
65
+ return
66
+ if (activeEl === container && this.editor.getSelectedShapeIds().length > 0) return
63
67
  if (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {
64
68
  container.classList.remove('tl-container__no-focus-ring')
65
69
  }
@@ -47,7 +47,8 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark({
47
47
  const ref = useRef<HTMLDivElement>(null)
48
48
  usePassThroughWheelEvents(ref)
49
49
 
50
- const url = 'https://tldraw.dev/?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'
50
+ const url =
51
+ 'https://tldraw.dev/pricing?utm_source=dotcom&utm_medium=organic&utm_campaign=watermark'
51
52
 
52
53
  return (
53
54
  <div
@@ -67,23 +68,10 @@ const UnlicensedWatermark = memo(function UnlicensedWatermark({
67
68
  markEventAsHandled(e)
68
69
  preventDefault(e)
69
70
  }}
70
- title="Unlicensed - click to get a license"
71
+ title="The tldraw SDK requires a license key to work in production. You can get a free 100-day trial license at tldraw.dev/pricing."
71
72
  onClick={() => runtime.openWindow(url, '_blank')}
72
- style={{
73
- position: 'absolute',
74
- pointerEvents: 'all',
75
- cursor: 'pointer',
76
- color: 'var(--tl-color-text)',
77
- opacity: 0.8,
78
- border: 0,
79
- padding: 0,
80
- backgroundColor: 'transparent',
81
- fontSize: '11px',
82
- fontWeight: '600',
83
- textAlign: 'center',
84
- }}
85
73
  >
86
- Unlicensed
74
+ Get a license for production
87
75
  </button>
88
76
  </div>
89
77
  )
@@ -130,7 +118,7 @@ const WatermarkInner = memo(function WatermarkInner({
130
118
  markEventAsHandled(e)
131
119
  preventDefault(e)
132
120
  }}
133
- title="made with tldraw"
121
+ title="Build infinite canvas applications with the tldraw SDK. Learn more at https://tldraw.dev."
134
122
  onClick={() => runtime.openWindow(url, '_blank')}
135
123
  style={{ mask: maskCss, WebkitMask: maskCss }}
136
124
  />
@@ -142,7 +130,8 @@ const LicenseStyles = memo(function LicenseStyles() {
142
130
  const editor = useEditor()
143
131
  const className = LicenseManager.className
144
132
 
145
- const CSS = `/* ------------------- SEE LICENSE -------------------
133
+ const CSS = `
134
+ /* ------------------- SEE LICENSE -------------------
146
135
  The tldraw watermark is part of tldraw's license. It is shown for unlicensed
147
136
  or "licensed-with-watermark" users. By using this library, you agree to
148
137
  preserve the watermark's behavior, keeping it visible, unobscured, and
@@ -151,87 +140,105 @@ available to user-interaction.
151
140
  To remove the watermark, please purchase a license at tldraw.dev.
152
141
  */
153
142
 
154
- .${className} {
155
- position: absolute;
156
- bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
157
- right: max(var(--tl-space-2), env(safe-area-inset-right));
158
- width: 96px;
159
- height: 32px;
160
- display: flex;
161
- align-items: center;
162
- justify-content: center;
163
- z-index: var(--tl-layer-watermark) !important;
164
- background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
165
- opacity: 1;
166
- border-radius: 5px;
167
- pointer-events: all;
168
- padding: 2px;
169
- box-sizing: content-box;
143
+ .${className} {
144
+ position: absolute;
145
+ bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
146
+ right: max(var(--tl-space-2), env(safe-area-inset-right));
147
+ width: 96px;
148
+ height: 32px;
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ z-index: var(--tl-layer-watermark) !important;
153
+ background-color: color-mix(in srgb, var(--tl-color-background) 62%, transparent);
154
+ opacity: 1;
155
+ border-radius: 5px;
156
+ pointer-events: all;
157
+ padding: 2px;
158
+ box-sizing: content-box;
159
+ }
160
+
161
+ .${className} > button {
162
+ position: absolute;
163
+ width: 96px;
164
+ height: 32px;
165
+ pointer-events: all;
166
+ cursor: inherit;
167
+ color: var(--tl-color-text);
168
+ opacity: .38;
169
+ border: 0;
170
+ padding: 0;
171
+ background-color: currentColor;
172
+ }
173
+
174
+ .${className}[data-debug='true'] {
175
+ bottom: max(46px, env(safe-area-inset-bottom));
176
+ }
177
+
178
+ .${className}[data-mobile='true'] {
179
+ border-radius: 4px 0px 0px 4px;
180
+ right: max(-2px, calc(env(safe-area-inset-right) - 2px));
181
+ width: 8px;
182
+ height: 48px;
183
+ }
184
+
185
+ .${className}[data-mobile='true'] > button {
186
+ width: 8px;
187
+ height: 32px;
188
+ }
189
+
190
+ .${className}[data-unlicensed='true'] > button {
191
+ font-size: 100px;
192
+ position: absolute;
193
+ pointer-events: all;
194
+ cursor: pointer;
195
+ color: var(--tl-color-text);
196
+ opacity: 0.8;
197
+ border: 0;
198
+ padding: 0;
199
+ background-color: transparent;
200
+ font-size: 11px;
201
+ font-weight: 600;
202
+ text-align: center;
203
+ }
204
+
205
+ .${className}[data-mobile='true'][data-unlicensed='true'] > button {
206
+ display: none;
207
+ }
208
+
209
+ @media (hover: hover) {
210
+ .${className}[data-licensed='false'] > button {
211
+ pointer-events: none;
170
212
  }
171
213
 
172
- .${className} > button {
173
- position: absolute;
174
- width: 96px;
175
- height: 32px;
176
- pointer-events: all;
177
- cursor: inherit;
178
- color: var(--tl-color-text);
179
- opacity: .38;
180
- border: 0;
181
- padding: 0;
182
- background-color: currentColor;
214
+ .${className}[data-licensed='false']:hover {
215
+ background-color: var(--tl-color-background);
216
+ transition: background-color 0.2s ease-in-out;
217
+ transition-delay: 0.32s;
183
218
  }
184
219
 
185
- .${className}[data-debug='true'] {
186
- bottom: max(46px, env(safe-area-inset-bottom));
220
+ .${className}[data-licensed='false']:hover > button {
221
+ animation: ${className}_delayed_link 0.2s forwards ease-in-out;
222
+ animation-delay: 0.32s;
187
223
  }
188
224
 
189
- .${className}[data-mobile='true'] {
190
- border-radius: 4px 0px 0px 4px;
191
- right: max(-2px, calc(env(safe-area-inset-right) - 2px));
192
- width: 8px;
193
- height: 48px;
225
+ .${className}[data-licensed='false'] > button:focus-visible {
226
+ opacity: 1;
194
227
  }
228
+ }
195
229
 
196
- .${className}[data-mobile='true'] > button {
197
- width: 8px;
198
- height: 32px;
230
+ @keyframes ${className}_delayed_link {
231
+ 0% {
232
+ cursor: inherit;
233
+ opacity: .38;
234
+ pointer-events: none;
199
235
  }
200
-
201
- @media (hover: hover) {
202
- .${className} > button {
203
- pointer-events: none;
204
- }
205
-
206
- .${className}:hover {
207
- background-color: var(--tl-color-background);
208
- transition: background-color 0.2s ease-in-out;
209
- transition-delay: 0.32s;
210
- }
211
-
212
- .${className}:hover > button {
213
- animation: ${className}_delayed_link 0.2s forwards ease-in-out;
214
- animation-delay: 0.32s;
215
- }
216
-
217
- .${className} > button:focus-visible {
218
- opacity: 1;
219
- }
236
+ 100% {
237
+ cursor: pointer;
238
+ opacity: 1;
239
+ pointer-events: all;
220
240
  }
221
-
222
-
223
- @keyframes ${className}_delayed_link {
224
- 0% {
225
- cursor: inherit;
226
- opacity: .38;
227
- pointer-events: none;
228
- }
229
- 100% {
230
- cursor: pointer;
231
- opacity: 1;
232
- pointer-events: all;
233
- }
234
- }`
241
+ }`
235
242
 
236
243
  return <style nonce={editor.options.nonce}>{CSS}</style>
237
244
  })
package/src/version.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.16.0-canary.ba3bc37d4418'
4
+ export const version = '3.16.0-canary.bf7be9dad88b'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-09-16T14:55:49.384Z',
8
- patch: '2025-09-16T14:55:49.384Z',
7
+ minor: '2025-09-17T15:01:00.589Z',
8
+ patch: '2025-09-17T15:01:00.589Z',
9
9
  }