tldraw 4.4.0-canary.afdcafe834b3 → 4.4.0-canary.b80d167101d1

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 (50) hide show
  1. package/dist-cjs/index.d.ts +113 -2
  2. package/dist-cjs/index.js +10 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js +6 -1
  5. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  6. package/dist-cjs/lib/defaultSideEffects.js +8 -0
  7. package/dist-cjs/lib/defaultSideEffects.js.map +2 -2
  8. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +2 -1
  9. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  10. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js +26 -3
  11. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js.map +3 -3
  12. package/dist-cjs/lib/ui/components/primitives/TldrawUiSelect.js +144 -0
  13. package/dist-cjs/lib/ui/components/primitives/TldrawUiSelect.js.map +7 -0
  14. package/dist-cjs/lib/ui/context/actions.js +3 -0
  15. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  16. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  17. package/dist-cjs/lib/ui/version.js +3 -3
  18. package/dist-cjs/lib/ui/version.js.map +1 -1
  19. package/dist-esm/index.d.mts +113 -2
  20. package/dist-esm/index.mjs +17 -1
  21. package/dist-esm/index.mjs.map +2 -2
  22. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs +6 -1
  23. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  24. package/dist-esm/lib/defaultSideEffects.mjs +8 -0
  25. package/dist-esm/lib/defaultSideEffects.mjs.map +2 -2
  26. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +2 -1
  27. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  28. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs +26 -3
  29. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs.map +3 -3
  30. package/dist-esm/lib/ui/components/primitives/TldrawUiSelect.mjs +114 -0
  31. package/dist-esm/lib/ui/components/primitives/TldrawUiSelect.mjs.map +7 -0
  32. package/dist-esm/lib/ui/context/actions.mjs +3 -0
  33. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  34. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  35. package/dist-esm/lib/ui/version.mjs +3 -3
  36. package/dist-esm/lib/ui/version.mjs.map +1 -1
  37. package/package.json +4 -5
  38. package/src/index.ts +15 -1
  39. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +12 -0
  40. package/src/lib/defaultSideEffects.ts +8 -0
  41. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -0
  42. package/src/lib/tools/selection-logic/updateHoveredShapeId.ts +54 -5
  43. package/src/lib/ui/components/primitives/TldrawUiSelect.tsx +211 -0
  44. package/src/lib/ui/context/actions.tsx +3 -0
  45. package/src/lib/ui/context/events.tsx +0 -1
  46. package/src/lib/ui/version.ts +3 -3
  47. package/src/lib/ui.css +46 -0
  48. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +2 -2
  49. package/src/test/commands/cameraState.test.ts +109 -0
  50. package/tldraw.css +51 -0
@@ -22,14 +22,15 @@ __export(updateHoveredShapeId_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(updateHoveredShapeId_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
- function _updateHoveredShapeId(editor) {
25
+ const hoverLockedEditors = /* @__PURE__ */ new WeakMap();
26
+ function getShapeToHover(editor) {
26
27
  const hitShape = editor.getShapeAtPoint(editor.inputs.getCurrentPagePoint(), {
27
28
  hitInside: false,
28
29
  hitLabels: false,
29
30
  margin: editor.options.hitTestMargin / editor.getZoomLevel(),
30
31
  renderingOnly: true
31
32
  });
32
- if (!hitShape) return editor.setHoveredShape(null);
33
+ if (!hitShape) return null;
33
34
  let shapeToHover = void 0;
34
35
  const outermostShape = editor.getOutermostSelectableShape(hitShape);
35
36
  if (outermostShape === hitShape) {
@@ -41,7 +42,29 @@ function _updateHoveredShapeId(editor) {
41
42
  shapeToHover = outermostShape;
42
43
  }
43
44
  }
44
- return editor.setHoveredShape(shapeToHover.id);
45
+ return shapeToHover.id;
46
+ }
47
+ function _updateHoveredShapeId(editor) {
48
+ const cameraMoving = editor.getCameraState() === "moving";
49
+ if (!cameraMoving) {
50
+ hoverLockedEditors.set(editor, false);
51
+ const nextHoveredId2 = getShapeToHover(editor);
52
+ return editor.setHoveredShape(nextHoveredId2);
53
+ }
54
+ if (hoverLockedEditors.get(editor)) {
55
+ return;
56
+ }
57
+ const currentHoveredId = editor.getHoveredShapeId();
58
+ if (!currentHoveredId) {
59
+ hoverLockedEditors.set(editor, true);
60
+ return;
61
+ }
62
+ const nextHoveredId = getShapeToHover(editor);
63
+ if (nextHoveredId === currentHoveredId) {
64
+ return;
65
+ }
66
+ editor.setHoveredShape(null);
67
+ hoverLockedEditors.set(editor, true);
45
68
  }
46
69
  const updateHoveredShapeId = (0, import_editor.throttle)(
47
70
  _updateHoveredShapeId,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/tools/selection-logic/updateHoveredShapeId.ts"],
4
- "sourcesContent": ["import { Editor, TLShape, throttle } from '@tldraw/editor'\n\nfunction _updateHoveredShapeId(editor: Editor) {\n\t// todo: consider replacing `get hoveredShapeId` with this; it would mean keeping hoveredShapeId in memory rather than in the store and possibly re-computing it more often than necessary\n\tconst hitShape = editor.getShapeAtPoint(editor.inputs.getCurrentPagePoint(), {\n\t\thitInside: false,\n\t\thitLabels: false,\n\t\tmargin: editor.options.hitTestMargin / editor.getZoomLevel(),\n\t\trenderingOnly: true,\n\t})\n\n\tif (!hitShape) return editor.setHoveredShape(null)\n\n\tlet shapeToHover: TLShape | undefined = undefined\n\n\tconst outermostShape = editor.getOutermostSelectableShape(hitShape)\n\n\tif (outermostShape === hitShape) {\n\t\tshapeToHover = hitShape\n\t} else {\n\t\tif (\n\t\t\toutermostShape.id === editor.getFocusedGroupId() ||\n\t\t\teditor.getSelectedShapeIds().includes(outermostShape.id)\n\t\t) {\n\t\t\tshapeToHover = hitShape\n\t\t} else {\n\t\t\tshapeToHover = outermostShape\n\t\t}\n\t}\n\n\treturn editor.setHoveredShape(shapeToHover.id)\n}\n\n/** @internal */\nexport const updateHoveredShapeId = throttle(\n\t_updateHoveredShapeId,\n\tprocess.env.NODE_ENV === 'test' ? 0 : 32\n)\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA0C;AAE1C,SAAS,sBAAsB,QAAgB;AAE9C,QAAM,WAAW,OAAO,gBAAgB,OAAO,OAAO,oBAAoB,GAAG;AAAA,IAC5E,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ,OAAO,QAAQ,gBAAgB,OAAO,aAAa;AAAA,IAC3D,eAAe;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,SAAU,QAAO,OAAO,gBAAgB,IAAI;AAEjD,MAAI,eAAoC;AAExC,QAAM,iBAAiB,OAAO,4BAA4B,QAAQ;AAElE,MAAI,mBAAmB,UAAU;AAChC,mBAAe;AAAA,EAChB,OAAO;AACN,QACC,eAAe,OAAO,OAAO,kBAAkB,KAC/C,OAAO,oBAAoB,EAAE,SAAS,eAAe,EAAE,GACtD;AACD,qBAAe;AAAA,IAChB,OAAO;AACN,qBAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAO,OAAO,gBAAgB,aAAa,EAAE;AAC9C;AAGO,MAAM,2BAAuB;AAAA,EACnC;AAAA,EACA,QAAQ,IAAI,aAAa,SAAS,IAAI;AACvC;",
6
- "names": []
4
+ "sourcesContent": ["import { Editor, TLShape, TLShapeId, throttle } from '@tldraw/editor'\n\n/*\nPerf optimization: Skip hover updates while panning.\n\nHit-testing shapes is expensive in large documents. When panning, we don't need\ncontinuous hover updates - we just need to resume when the camera stops.\n\nThe logic:\n1. Camera idle \u2192 update hover normally, unlock\n2. Camera moving + locked \u2192 skip entirely (no hit-testing)\n3. Camera moving + no current hover \u2192 lock immediately\n4. Camera moving + same shape \u2192 keep current hover (no change needed)\n5. Camera moving + different shape \u2192 clear hover and lock\n\nThis means: when you start panning over a shape, it stays hovered until\nyour cursor moves off it, then hover clears and we stop hit-testing until\nthe camera stops.\n*/\n\n// Track per-editor state for hover updates during camera movement\nconst hoverLockedEditors = new WeakMap<Editor, boolean>()\n\nfunction getShapeToHover(editor: Editor): TLShapeId | null {\n\tconst hitShape = editor.getShapeAtPoint(editor.inputs.getCurrentPagePoint(), {\n\t\thitInside: false,\n\t\thitLabels: false,\n\t\tmargin: editor.options.hitTestMargin / editor.getZoomLevel(),\n\t\trenderingOnly: true,\n\t})\n\n\tif (!hitShape) return null\n\n\tlet shapeToHover: TLShape | undefined = undefined\n\n\tconst outermostShape = editor.getOutermostSelectableShape(hitShape)\n\n\tif (outermostShape === hitShape) {\n\t\tshapeToHover = hitShape\n\t} else {\n\t\tif (\n\t\t\toutermostShape.id === editor.getFocusedGroupId() ||\n\t\t\teditor.getSelectedShapeIds().includes(outermostShape.id)\n\t\t) {\n\t\t\tshapeToHover = hitShape\n\t\t} else {\n\t\t\tshapeToHover = outermostShape\n\t\t}\n\t}\n\n\treturn shapeToHover.id\n}\n\nfunction _updateHoveredShapeId(editor: Editor) {\n\tconst cameraMoving = editor.getCameraState() === 'moving'\n\n\tif (!cameraMoving) {\n\t\thoverLockedEditors.set(editor, false)\n\t\tconst nextHoveredId = getShapeToHover(editor)\n\t\treturn editor.setHoveredShape(nextHoveredId)\n\t}\n\n\tif (hoverLockedEditors.get(editor)) {\n\t\treturn\n\t}\n\n\tconst currentHoveredId = editor.getHoveredShapeId()\n\n\tif (!currentHoveredId) {\n\t\thoverLockedEditors.set(editor, true)\n\t\treturn\n\t}\n\n\tconst nextHoveredId = getShapeToHover(editor)\n\tif (nextHoveredId === currentHoveredId) {\n\t\treturn\n\t}\n\n\teditor.setHoveredShape(null)\n\thoverLockedEditors.set(editor, true)\n}\n\n/** @internal */\nexport const updateHoveredShapeId = throttle(\n\t_updateHoveredShapeId,\n\tprocess.env.NODE_ENV === 'test' ? 0 : 32\n)\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAqD;AAqBrD,MAAM,qBAAqB,oBAAI,QAAyB;AAExD,SAAS,gBAAgB,QAAkC;AAC1D,QAAM,WAAW,OAAO,gBAAgB,OAAO,OAAO,oBAAoB,GAAG;AAAA,IAC5E,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ,OAAO,QAAQ,gBAAgB,OAAO,aAAa;AAAA,IAC3D,eAAe;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,eAAoC;AAExC,QAAM,iBAAiB,OAAO,4BAA4B,QAAQ;AAElE,MAAI,mBAAmB,UAAU;AAChC,mBAAe;AAAA,EAChB,OAAO;AACN,QACC,eAAe,OAAO,OAAO,kBAAkB,KAC/C,OAAO,oBAAoB,EAAE,SAAS,eAAe,EAAE,GACtD;AACD,qBAAe;AAAA,IAChB,OAAO;AACN,qBAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAO,aAAa;AACrB;AAEA,SAAS,sBAAsB,QAAgB;AAC9C,QAAM,eAAe,OAAO,eAAe,MAAM;AAEjD,MAAI,CAAC,cAAc;AAClB,uBAAmB,IAAI,QAAQ,KAAK;AACpC,UAAMA,iBAAgB,gBAAgB,MAAM;AAC5C,WAAO,OAAO,gBAAgBA,cAAa;AAAA,EAC5C;AAEA,MAAI,mBAAmB,IAAI,MAAM,GAAG;AACnC;AAAA,EACD;AAEA,QAAM,mBAAmB,OAAO,kBAAkB;AAElD,MAAI,CAAC,kBAAkB;AACtB,uBAAmB,IAAI,QAAQ,IAAI;AACnC;AAAA,EACD;AAEA,QAAM,gBAAgB,gBAAgB,MAAM;AAC5C,MAAI,kBAAkB,kBAAkB;AACvC;AAAA,EACD;AAEA,SAAO,gBAAgB,IAAI;AAC3B,qBAAmB,IAAI,QAAQ,IAAI;AACpC;AAGO,MAAM,2BAAuB;AAAA,EACnC;AAAA,EACA,QAAQ,IAAI,aAAa,SAAS,IAAI;AACvC;",
6
+ "names": ["nextHoveredId"]
7
7
  }
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var TldrawUiSelect_exports = {};
30
+ __export(TldrawUiSelect_exports, {
31
+ TldrawUiSelect: () => TldrawUiSelect,
32
+ TldrawUiSelectContent: () => TldrawUiSelectContent,
33
+ TldrawUiSelectItem: () => TldrawUiSelectItem,
34
+ TldrawUiSelectTrigger: () => TldrawUiSelectTrigger,
35
+ TldrawUiSelectValue: () => TldrawUiSelectValue
36
+ });
37
+ module.exports = __toCommonJS(TldrawUiSelect_exports);
38
+ var import_jsx_runtime = require("react/jsx-runtime");
39
+ var import_editor = require("@tldraw/editor");
40
+ var import_classnames = __toESM(require("classnames"), 1);
41
+ var import_radix_ui = require("radix-ui");
42
+ var React = __toESM(require("react"), 1);
43
+ var import_useMenuIsOpen = require("../../hooks/useMenuIsOpen");
44
+ var import_TldrawUiIcon = require("./TldrawUiIcon");
45
+ function TldrawUiSelect({
46
+ id,
47
+ value,
48
+ onValueChange,
49
+ onOpenChange,
50
+ disabled,
51
+ className,
52
+ children,
53
+ "data-testid": dataTestId,
54
+ "aria-label": ariaLabel
55
+ }) {
56
+ const [open, handleOpenChange] = (0, import_useMenuIsOpen.useMenuIsOpen)(id, onOpenChange);
57
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
58
+ import_radix_ui.Select.Root,
59
+ {
60
+ value,
61
+ onValueChange,
62
+ onOpenChange: handleOpenChange,
63
+ open,
64
+ disabled,
65
+ dir: "ltr",
66
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
67
+ "div",
68
+ {
69
+ id,
70
+ className: (0, import_classnames.default)("tlui-select", className),
71
+ "data-testid": dataTestId,
72
+ "aria-label": ariaLabel,
73
+ children
74
+ }
75
+ )
76
+ }
77
+ );
78
+ }
79
+ const TldrawUiSelectTrigger = React.forwardRef(
80
+ function TldrawUiSelectTrigger2({ children, className }, ref) {
81
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
82
+ import_radix_ui.Select.Trigger,
83
+ {
84
+ ref,
85
+ className: (0, import_classnames.default)("tlui-button tlui-select__trigger", className),
86
+ children: [
87
+ children,
88
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Select.Icon, { className: "tlui-select__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiIcon.TldrawUiIcon, { icon: "chevron-down", label: "", small: true }) })
89
+ ]
90
+ }
91
+ );
92
+ }
93
+ );
94
+ function TldrawUiSelectValue({ placeholder, icon, children }) {
95
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Select.Value, { placeholder, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "tlui-select__value", children: [
96
+ icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiIcon.TldrawUiIcon, { icon, label: "", small: true }),
97
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tlui-button__label", children })
98
+ ] }) });
99
+ }
100
+ function TldrawUiSelectContent({
101
+ children,
102
+ side = "bottom",
103
+ align = "start",
104
+ className
105
+ }) {
106
+ const container = (0, import_editor.useContainer)();
107
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Select.Portal, { container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
108
+ import_radix_ui.Select.Content,
109
+ {
110
+ className: (0, import_classnames.default)("tlui-menu tlui-select__content", className),
111
+ position: "popper",
112
+ side,
113
+ align,
114
+ sideOffset: 4,
115
+ collisionPadding: 4,
116
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Select.Viewport, { className: "tlui-select__viewport", children })
117
+ }
118
+ ) });
119
+ }
120
+ function TldrawUiSelectItem({
121
+ value,
122
+ label,
123
+ icon,
124
+ disabled,
125
+ className
126
+ }) {
127
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
128
+ import_radix_ui.Select.Item,
129
+ {
130
+ value,
131
+ disabled,
132
+ className: (0, import_classnames.default)(
133
+ "tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item",
134
+ className
135
+ ),
136
+ children: [
137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiIcon.TldrawUiIcon, { small: true, icon: "check", label: "", className: "tlui-select__item-indicator" }),
138
+ icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiIcon.TldrawUiIcon, { icon, label: "", small: true }),
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_radix_ui.Select.ItemText, { className: "tlui-button__label", children: label })
140
+ ]
141
+ }
142
+ );
143
+ }
144
+ //# sourceMappingURL=TldrawUiSelect.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiSelect.tsx"],
4
+ "sourcesContent": ["import { useContainer } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { Select as _Select } from 'radix-ui'\nimport * as React from 'react'\nimport { useMenuIsOpen } from '../../hooks/useMenuIsOpen'\nimport { TLUiIconType } from '../../icon-types'\nimport { TldrawUiIcon } from './TldrawUiIcon'\n\n/* --------------------- Root --------------------- */\n\n/** @public */\nexport interface TLUiSelectProps {\n\tid: string\n\tvalue: string\n\tonValueChange(value: string): void\n\tonOpenChange?(isOpen: boolean): void\n\tdisabled?: boolean\n\tclassName?: string\n\tchildren: React.ReactNode\n\t'data-testid'?: string\n\t'aria-label'?: string\n}\n\n/**\n * A select dropdown component.\n *\n * @example\n * ```tsx\n * <TldrawUiSelect id=\"my-select\" value={value} onValueChange={setValue}>\n * <TldrawUiSelectTrigger>\n * <TldrawUiSelectValue placeholder=\"Select...\" />\n * </TldrawUiSelectTrigger>\n * <TldrawUiSelectContent>\n * <TldrawUiSelectItem value=\"one\" label=\"One\" />\n * <TldrawUiSelectItem value=\"two\" label=\"Two\" />\n * </TldrawUiSelectContent>\n * </TldrawUiSelect>\n * ```\n *\n * @public\n * @react\n */\nexport function TldrawUiSelect({\n\tid,\n\tvalue,\n\tonValueChange,\n\tonOpenChange,\n\tdisabled,\n\tclassName,\n\tchildren,\n\t'data-testid': dataTestId,\n\t'aria-label': ariaLabel,\n}: TLUiSelectProps) {\n\tconst [open, handleOpenChange] = useMenuIsOpen(id, onOpenChange)\n\n\treturn (\n\t\t<_Select.Root\n\t\t\tvalue={value}\n\t\t\tonValueChange={onValueChange}\n\t\t\tonOpenChange={handleOpenChange}\n\t\t\topen={open}\n\t\t\tdisabled={disabled}\n\t\t\tdir=\"ltr\"\n\t\t>\n\t\t\t<div\n\t\t\t\tid={id}\n\t\t\t\tclassName={classNames('tlui-select', className)}\n\t\t\t\tdata-testid={dataTestId}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</_Select.Root>\n\t)\n}\n\n/* --------------------- Trigger --------------------- */\n\n/** @public */\nexport interface TLUiSelectTriggerProps {\n\tchildren: React.ReactNode\n\tclassName?: string\n}\n\n/**\n * The trigger button for the select dropdown.\n *\n * @public\n * @react\n */\nexport const TldrawUiSelectTrigger = React.forwardRef<HTMLButtonElement, TLUiSelectTriggerProps>(\n\tfunction TldrawUiSelectTrigger({ children, className }, ref) {\n\t\treturn (\n\t\t\t<_Select.Trigger\n\t\t\t\tref={ref}\n\t\t\t\tclassName={classNames('tlui-button tlui-select__trigger', className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<_Select.Icon className=\"tlui-select__chevron\">\n\t\t\t\t\t<TldrawUiIcon icon=\"chevron-down\" label=\"\" small />\n\t\t\t\t</_Select.Icon>\n\t\t\t</_Select.Trigger>\n\t\t)\n\t}\n)\n\n/* --------------------- Value --------------------- */\n\n/** @public */\nexport interface TLUiSelectValueProps {\n\tplaceholder?: string\n\ticon?: TLUiIconType | Exclude<string, TLUiIconType>\n\tchildren?: React.ReactNode\n}\n\n/**\n * Displays the currently selected value in the trigger.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectValue({ placeholder, icon, children }: TLUiSelectValueProps) {\n\treturn (\n\t\t<_Select.Value placeholder={placeholder}>\n\t\t\t<span className=\"tlui-select__value\">\n\t\t\t\t{icon && <TldrawUiIcon icon={icon} label=\"\" small />}\n\t\t\t\t<span className=\"tlui-button__label\">{children}</span>\n\t\t\t</span>\n\t\t</_Select.Value>\n\t)\n}\n\n/* --------------------- Content --------------------- */\n\n/** @public */\nexport interface TLUiSelectContentProps {\n\tchildren: React.ReactNode\n\tside?: 'top' | 'bottom'\n\talign?: 'start' | 'center' | 'end'\n\tclassName?: string\n}\n\n/**\n * The dropdown content container for select items.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectContent({\n\tchildren,\n\tside = 'bottom',\n\talign = 'start',\n\tclassName,\n}: TLUiSelectContentProps) {\n\tconst container = useContainer()\n\n\treturn (\n\t\t<_Select.Portal container={container}>\n\t\t\t<_Select.Content\n\t\t\t\tclassName={classNames('tlui-menu tlui-select__content', className)}\n\t\t\t\tposition=\"popper\"\n\t\t\t\tside={side}\n\t\t\t\talign={align}\n\t\t\t\tsideOffset={4}\n\t\t\t\tcollisionPadding={4}\n\t\t\t>\n\t\t\t\t<_Select.Viewport className=\"tlui-select__viewport\">{children}</_Select.Viewport>\n\t\t\t</_Select.Content>\n\t\t</_Select.Portal>\n\t)\n}\n\n/* --------------------- Item --------------------- */\n\n/** @public */\nexport interface TLUiSelectItemProps {\n\tvalue: string\n\tlabel: string\n\ticon?: TLUiIconType | Exclude<string, TLUiIconType>\n\tdisabled?: boolean\n\tclassName?: string\n}\n\n/**\n * An item in the select dropdown. Styled to match TldrawUiMenuCheckboxItem.\n *\n * @public\n * @react\n */\nexport function TldrawUiSelectItem({\n\tvalue,\n\tlabel,\n\ticon,\n\tdisabled,\n\tclassName,\n}: TLUiSelectItemProps) {\n\treturn (\n\t\t<_Select.Item\n\t\t\tvalue={value}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={classNames(\n\t\t\t\t'tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<TldrawUiIcon small icon=\"check\" label=\"\" className=\"tlui-select__item-indicator\" />\n\t\t\t{icon && <TldrawUiIcon icon={icon} label=\"\" small />}\n\t\t\t<_Select.ItemText className=\"tlui-button__label\">{label}</_Select.ItemText>\n\t\t</_Select.Item>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgEG;AAhEH,oBAA6B;AAC7B,wBAAuB;AACvB,sBAAkC;AAClC,YAAuB;AACvB,2BAA8B;AAE9B,0BAA6B;AAoCtB,SAAS,eAAe;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AACf,GAAoB;AACnB,QAAM,CAAC,MAAM,gBAAgB,QAAI,oCAAc,IAAI,YAAY;AAE/D,SACC;AAAA,IAAC,gBAAAA,OAAQ;AAAA,IAAR;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,KAAI;AAAA,MAEJ;AAAA,QAAC;AAAA;AAAA,UACA;AAAA,UACA,eAAW,kBAAAC,SAAW,eAAe,SAAS;AAAA,UAC9C,eAAa;AAAA,UACb,cAAY;AAAA,UAEX;AAAA;AAAA,MACF;AAAA;AAAA,EACD;AAEF;AAgBO,MAAM,wBAAwB,MAAM;AAAA,EAC1C,SAASC,uBAAsB,EAAE,UAAU,UAAU,GAAG,KAAK;AAC5D,WACC;AAAA,MAAC,gBAAAF,OAAQ;AAAA,MAAR;AAAA,QACA;AAAA,QACA,eAAW,kBAAAC,SAAW,oCAAoC,SAAS;AAAA,QAElE;AAAA;AAAA,UACD,4CAAC,gBAAAD,OAAQ,MAAR,EAAa,WAAU,wBACvB,sDAAC,oCAAa,MAAK,gBAAe,OAAM,IAAG,OAAK,MAAC,GAClD;AAAA;AAAA;AAAA,IACD;AAAA,EAEF;AACD;AAiBO,SAAS,oBAAoB,EAAE,aAAa,MAAM,SAAS,GAAyB;AAC1F,SACC,4CAAC,gBAAAA,OAAQ,OAAR,EAAc,aACd,uDAAC,UAAK,WAAU,sBACd;AAAA,YAAQ,4CAAC,oCAAa,MAAY,OAAM,IAAG,OAAK,MAAC;AAAA,IAClD,4CAAC,UAAK,WAAU,sBAAsB,UAAS;AAAA,KAChD,GACD;AAEF;AAkBO,SAAS,sBAAsB;AAAA,EACrC;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AACD,GAA2B;AAC1B,QAAM,gBAAY,4BAAa;AAE/B,SACC,4CAAC,gBAAAA,OAAQ,QAAR,EAAe,WACf;AAAA,IAAC,gBAAAA,OAAQ;AAAA,IAAR;AAAA,MACA,eAAW,kBAAAC,SAAW,kCAAkC,SAAS;AAAA,MACjE,UAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,kBAAkB;AAAA,MAElB,sDAAC,gBAAAD,OAAQ,UAAR,EAAiB,WAAU,yBAAyB,UAAS;AAAA;AAAA,EAC/D,GACD;AAEF;AAmBO,SAAS,mBAAmB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,SACC;AAAA,IAAC,gBAAAA,OAAQ;AAAA,IAAR;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAW,kBAAAC;AAAA,QACV;AAAA,QACA;AAAA,MACD;AAAA,MAEA;AAAA,oDAAC,oCAAa,OAAK,MAAC,MAAK,SAAQ,OAAM,IAAG,WAAU,+BAA8B;AAAA,QACjF,QAAQ,4CAAC,oCAAa,MAAY,OAAM,IAAG,OAAK,MAAC;AAAA,QAClD,4CAAC,gBAAAD,OAAQ,UAAR,EAAiB,WAAU,sBAAsB,iBAAM;AAAA;AAAA;AAAA,EACzD;AAEF;",
6
+ "names": ["_Select", "classNames", "TldrawUiSelectTrigger"]
7
+ }
@@ -1335,6 +1335,7 @@ function ActionsProvider({ overrides, children }) {
1335
1335
  label: "action.toggle-lock",
1336
1336
  kbd: "shift+l",
1337
1337
  onSelect(source) {
1338
+ if (!canApplySelectionAction()) return;
1338
1339
  editor.markHistoryStoppingPoint("locking");
1339
1340
  trackEvent("toggle-lock", { source });
1340
1341
  editor.toggleLock(editor.getSelectedShapeIds());
@@ -1516,6 +1517,7 @@ function ActionsProvider({ overrides, children }) {
1516
1517
  label: "a11y.enlarge-shape",
1517
1518
  kbd: "cmd+alt+shift+=,ctrl+alt+shift+=",
1518
1519
  onSelect: async (source) => {
1520
+ if (!canApplySelectionAction()) return;
1519
1521
  scaleShapes(1.1);
1520
1522
  trackEvent("enlarge-shapes", { source });
1521
1523
  }
@@ -1525,6 +1527,7 @@ function ActionsProvider({ overrides, children }) {
1525
1527
  label: "a11y.shrink-shape",
1526
1528
  kbd: "cmd+alt+shift+-,ctrl+alt+shift+-",
1527
1529
  onSelect: async (source) => {
1530
+ if (!canApplySelectionAction()) return;
1528
1531
  scaleShapes(1 / 1.1);
1529
1532
  trackEvent("shrink-shapes", { source });
1530
1533
  }