UNPKG

tldraw

Version:

A tiny little drawing editor.

351 lines (350 loc) • 12.8 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var TldrawUiMenuItem_exports = {}; __export(TldrawUiMenuItem_exports, { TldrawUiMenuItem: () => TldrawUiMenuItem }); module.exports = __toCommonJS(TldrawUiMenuItem_exports); var import_jsx_runtime = require("react/jsx-runtime"); var import_editor = require("@tldraw/editor"); var import_radix_ui = require("radix-ui"); var import_react = require("react"); var import_actions = require("../../../context/actions"); var import_useReadonly = require("../../../hooks/useReadonly"); var import_useTranslation = require("../../../hooks/useTranslation/useTranslation"); var import_kbd_utils = require("../../../kbd-utils"); var import_Spinner = require("../../Spinner"); var import_TldrawUiButton = require("../Button/TldrawUiButton"); var import_TldrawUiButtonIcon = require("../Button/TldrawUiButtonIcon"); var import_TldrawUiButtonLabel = require("../Button/TldrawUiButtonLabel"); var import_TldrawUiDropdownMenu = require("../TldrawUiDropdownMenu"); var import_TldrawUiKbd = require("../TldrawUiKbd"); var import_TldrawUiToolbar = require("../TldrawUiToolbar"); var import_TldrawUiTooltip = require("../TldrawUiTooltip"); var import_TldrawUiMenuContext = require("./TldrawUiMenuContext"); function TldrawUiMenuItem({ disabled = false, spinner = false, readonlyOk = false, id, kbd, label, icon, iconLeft, onSelect, noClose, isSelected, onDragStart }) { const { type: menuType, sourceId } = (0, import_TldrawUiMenuContext.useTldrawUiMenuContext)(); const msg = (0, import_useTranslation.useTranslation)(); const [disableClicks, setDisableClicks] = (0, import_react.useState)(false); const isReadonlyMode = (0, import_useReadonly.useReadonly)(); if (isReadonlyMode && !readonlyOk) return null; const labelToUse = (0, import_actions.unwrapLabel)(label, menuType); const kbdToUse = kbd ? (0, import_kbd_utils.kbdStr)(kbd) : void 0; const labelStr = labelToUse ? msg(labelToUse) : void 0; const titleStr = labelStr && kbdToUse ? `${labelStr} ${kbdToUse}` : labelStr; switch (menuType) { case "menu": { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiDropdownMenu.TldrawUiDropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_TldrawUiButton.TldrawUiButton, { type: "menu", "data-testid": `${sourceId}.${id}`, disabled, onClick: (e) => { if (noClose) { (0, import_editor.preventDefault)(e); } if (disableClicks) { setDisableClicks(false); } else { onSelect(sourceId); } }, children: [ iconLeft && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon: iconLeft, small: true }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonLabel.TldrawUiButtonLabel, { children: labelStr }), kbd && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiKbd.TldrawUiKbd, { children: kbd }) ] } ) }); } case "context-menu": { if (disabled) return null; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_radix_ui.ContextMenu.Item, { dir: "ltr", draggable: false, className: "tlui-button tlui-button__menu", "data-testid": `${sourceId}.${id}`, onSelect: (e) => { if (noClose) (0, import_editor.preventDefault)(e); if (disableClicks) { setDisableClicks(false); } else { onSelect(sourceId); } }, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "tlui-button__label", draggable: false, children: labelStr }), iconLeft && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon: iconLeft, small: true }), kbd && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiKbd.TldrawUiKbd, { children: kbd }), spinner && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Spinner.Spinner, {}) ] } ); } case "small-icons": case "icons": { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiToolbar.TldrawUiToolbarButton, { "data-testid": `${sourceId}.${id}`, type: "icon", title: titleStr, disabled, onClick: () => onSelect(sourceId), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon, small: true }) } ); } case "keyboard-shortcuts": { if (!kbd) { console.warn( `Menu item '${label}' isn't shown in the keyboard shortcuts dialog because it doesn't have a keyboard shortcut.` ); return null; } return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "tlui-shortcuts-dialog__key-pair", "data-testid": `${sourceId}.${id}`, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tlui-shortcuts-dialog__key-pair__key", children: labelStr }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tlui-shortcuts-dialog__key-pair__value", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiKbd.TldrawUiKbd, { visibleOnMobileLayout: true, children: kbd }) }) ] }); } case "helper-buttons": { return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_TldrawUiButton.TldrawUiButton, { type: "low", "data-testid": `${sourceId}.${id}`, onClick: () => onSelect(sourceId), children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonLabel.TldrawUiButtonLabel, { children: labelStr }) ] } ); } case "toolbar": { if (onDragStart) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( DraggableToolbarButton, { id, icon, onSelect, onDragStart, labelStr, titleStr, disabled, isSelected } ); } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiToolbar.TldrawUiToolbarButton, { "aria-label": labelStr, "aria-pressed": isSelected ? "true" : "false", "data-testid": `tools.${id}`, "data-value": id, disabled, onClick: () => onSelect("toolbar"), onTouchStart: (e) => { (0, import_editor.preventDefault)(e); onSelect("toolbar"); }, title: titleStr, type: "tool", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon }) } ); } case "toolbar-overflow": { if (onDragStart) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( DraggableToolbarButton, { id, icon, onSelect, onDragStart, labelStr, titleStr, disabled, isSelected, overflow: true } ); } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiToolbar.TldrawUiToolbarButton, { "aria-label": labelStr, "aria-pressed": isSelected ? "true" : "false", isActive: isSelected, "data-testid": `tools.more.${id}`, "data-value": id, disabled, onClick: () => onSelect("toolbar"), title: titleStr, type: "icon", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon }) } ); } default: { throw (0, import_editor.exhaustiveSwitchError)(menuType); } } } function useDraggableEvents(onDragStart, onSelect) { const editor = (0, import_editor.useEditor)(); const events = (0, import_react.useMemo)(() => { let state = { name: "idle" }; function handlePointerDown(e) { state = { name: "pointing", screenSpaceStart: { x: e.clientX, y: e.clientY } }; e.currentTarget.setPointerCapture(e.pointerId); } function handlePointerMove(e) { if (e.isSpecialRedispatchedEvent) return; if (state.name === "pointing") { const distanceSq = import_editor.Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY }); if (distanceSq > (editor.getInstanceState().isCoarsePointer ? editor.options.uiCoarseDragDistanceSquared : editor.options.uiDragDistanceSquared)) { const screenSpaceStart = state.screenSpaceStart; state = { name: "dragging", screenSpaceStart }; editor.run(() => { editor.setCurrentTool("select"); editor.dispatch({ type: "pointer", target: "canvas", name: "pointer_down", ...(0, import_editor.getPointerInfo)(editor, e), point: screenSpaceStart }); editor.selectNone(); onDragStart?.("toolbar", { type: "pointer", target: "canvas", name: "pointer_move", ...(0, import_editor.getPointerInfo)(editor, e), point: screenSpaceStart }); (0, import_TldrawUiTooltip.hideAllTooltips)(); editor.getContainer().focus(); }); } } } function handlePointerUp(e) { if (e.isSpecialRedispatchedEvent) return; e.currentTarget.releasePointerCapture(e.pointerId); editor.dispatch({ type: "pointer", target: "canvas", name: "pointer_up", ...(0, import_editor.getPointerInfo)(editor, e) }); } function handleClick() { if (state.name === "dragging" || state.name === "dragged") { state = { name: "idle" }; return true; } state = { name: "idle" }; onSelect?.("toolbar"); return false; } return { onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onClick: handleClick }; }, [onDragStart, editor, onSelect]); return events; } function DraggableToolbarButton({ id, labelStr, titleStr, disabled, isSelected, icon, onSelect, onDragStart, overflow }) { const events = useDraggableEvents(onDragStart, onSelect); if (overflow) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiToolbar.TldrawUiToolbarButton, { "aria-label": labelStr, "aria-pressed": isSelected ? "true" : "false", isActive: isSelected, className: "tlui-button-grid__button", "data-testid": `tools.more.${id}`, "data-value": id, disabled, title: titleStr, type: "icon", ...events, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon }) } ); } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_TldrawUiToolbar.TldrawUiToolbarButton, { "aria-label": labelStr, "aria-pressed": isSelected ? "true" : "false", "data-testid": `tools.${id}`, "data-value": id, disabled, onTouchStart: (e) => { (0, import_editor.preventDefault)(e); onSelect("toolbar"); }, title: titleStr, type: "tool", ...events, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon }) } ); } //# sourceMappingURL=TldrawUiMenuItem.js.map