tldraw 3.15.0-next.f1dfcef63951 → 3.16.0-next.c30b1b5e551a
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.d.ts +161 -95
- package/dist-cjs/index.js +42 -31
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawImage.js +5 -2
- package/dist-cjs/lib/TldrawImage.js.map +3 -3
- package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
- package/dist-cjs/lib/canvas/TldrawCropHandles.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawHandles.js +1 -1
- package/dist-cjs/lib/canvas/TldrawHandles.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawOverlays.js +1 -1
- package/dist-cjs/lib/canvas/TldrawOverlays.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +279 -271
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +1 -0
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +22 -36
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js +16 -4
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +5 -5
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +15 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PathBuilder.js +21 -3
- package/dist-cjs/lib/shapes/shared/PathBuilder.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -0
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -0
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -11
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/styles.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +43 -22
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +2 -15
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +5 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +8 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +8 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +8 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +51 -1
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +1 -0
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +3 -4
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/Spinner.js +2 -25
- package/dist-cjs/lib/ui/components/Spinner.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +2 -1
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +16 -0
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButtonIcon.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +35 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +6 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +0 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +42 -8
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +24 -7
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +8 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +2 -1
- package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +1 -1
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
- package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +3 -2
- package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
- package/dist-esm/index.d.mts +161 -95
- package/dist-esm/index.mjs +154 -135
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawImage.mjs +5 -2
- package/dist-esm/lib/TldrawImage.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawCropHandles.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawCropHandles.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawHandles.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawHandles.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawOverlays.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawOverlays.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +279 -271
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +1 -0
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +24 -36
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +19 -5
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +3 -0
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +5 -5
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +15 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PathBuilder.mjs +22 -3
- package/dist-esm/lib/shapes/shared/PathBuilder.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -0
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -0
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -11
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/styles.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +43 -22
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +2 -15
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +5 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +8 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +8 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +8 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +51 -1
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +2 -0
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +3 -4
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Spinner.mjs +3 -26
- package/dist-esm/lib/ui/components/Spinner.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +2 -1
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +16 -0
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButtonIcon.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs +1 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +36 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +6 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +0 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +42 -8
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +24 -7
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +8 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +2 -1
- package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +1 -1
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
- package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +3 -2
- package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
- package/package.json +4 -3
- package/src/index.ts +174 -160
- package/src/lib/TldrawImage.tsx +6 -2
- package/src/lib/canvas/TldrawCropHandles.tsx +3 -1
- package/src/lib/canvas/TldrawHandles.tsx +5 -1
- package/src/lib/canvas/TldrawOverlays.tsx +1 -1
- package/src/lib/canvas/TldrawSelectionForeground.tsx +5 -1
- package/src/lib/defaultExternalContentHandlers.ts +2 -1
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +5 -5
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +25 -39
- package/src/lib/shapes/arrow/arrowLabel.ts +23 -3
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -0
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +5 -7
- package/src/lib/shapes/line/LineShapeUtil.tsx +19 -2
- package/src/lib/shapes/shared/PathBuilder.test.tsx +1 -1
- package/src/lib/shapes/shared/PathBuilder.tsx +35 -1
- package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -0
- package/src/lib/shapes/shared/RichTextLabel.tsx +1 -0
- package/src/lib/shapes/text/TextShapeUtil.tsx +5 -12
- package/src/lib/styles.tsx +3 -1
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +54 -30
- package/src/lib/tools/SelectTool/childStates/Idle.ts +2 -24
- package/src/lib/tools/SelectTool/childStates/PointingShape.ts +7 -0
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +12 -1
- package/src/lib/tools/SelectTool/childStates/Rotating.ts +11 -0
- package/src/lib/tools/SelectTool/childStates/Translating.ts +11 -0
- package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -0
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +40 -0
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +2 -0
- package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +3 -4
- package/src/lib/ui/components/Spinner.tsx +2 -24
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +1 -0
- package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +3 -1
- package/src/lib/ui/components/menu-items.tsx +17 -0
- package/src/lib/ui/components/primitives/Button/TldrawUiButtonIcon.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiDialog.tsx +1 -1
- package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +41 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +6 -1
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +4 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +2 -2
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -4
- package/src/lib/ui/context/actions.tsx +44 -9
- package/src/lib/ui/context/events.tsx +4 -2
- package/src/lib/ui/hooks/menu-hooks.ts +1 -0
- package/src/lib/ui/hooks/useClipboardEvents.ts +31 -10
- package/src/lib/ui/hooks/useKeyboardShortcuts.ts +3 -2
- package/src/lib/ui/hooks/useTools.tsx +2 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +8 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +8 -0
- package/src/lib/ui/kbd-utils.ts +2 -1
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +8 -22
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +16 -2
- package/src/lib/utils/excalidraw/putExcalidrawContent.ts +1 -1
- package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +24 -3
- package/src/lib/utils/tldr/buildFromV1Document.ts +2 -1
- package/src/test/Editor.test.tsx +68 -1
- package/src/test/SelectTool.test.ts +37 -11
- package/src/test/commands/clipboard.test.ts +1 -1
- package/src/test/commands/deletePage.test.ts +84 -1
- package/src/test/navigation.test.ts +254 -0
- package/src/test/shapeutils.test.ts +394 -45
- package/tldraw.css +29 -49
- package/src/test/editor.test.ts +0 -77
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/frame/FrameShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tDefaultColorStyle,\n\tGeometry2d,\n\tGroup2d,\n\tRectangle2d,\n\tSVGContainer,\n\tSvgExportContext,\n\tTLClickEventInfo,\n\tTLDragShapesOutInfo,\n\tTLDragShapesOverInfo,\n\tTLFrameShape,\n\tTLFrameShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLShapeUtilConstructor,\n\tclamp,\n\tcompact,\n\tframeShapeMigrations,\n\tframeShapeProps,\n\tgetDefaultColorTheme,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { fitFrameToContent, getFrameChildrenBounds } from '../../utils/frames/frames'\nimport {\n\tTLCreateTextJsxFromSpansOpts,\n\tcreateTextJsxFromSpans,\n} from '../shared/createTextJsxFromSpans'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { FrameHeading } from './components/FrameHeading'\nimport {\n\tgetFrameHeadingOpts,\n\tgetFrameHeadingSide,\n\tgetFrameHeadingSize,\n\tgetFrameHeadingTranslation,\n} from './frameHelpers'\n\n// Some of these values are repeated in CSS and need to match\nconst FRAME_HEADING_EXTRA_WIDTH = 12\nconst FRAME_HEADING_MIN_WIDTH = 32\nconst FRAME_HEADING_NOCOLORS_OFFSET_X = -7\nconst FRAME_HEADING_OFFSET_Y = 4\n\n/** @public */\nexport interface FrameShapeOptions {\n\t/**\n\t * When true, the frame will display colors for the shape's headings and background.\n\t */\n\tshowColors: boolean\n}\n\nexport function defaultEmptyAs(str: string, dflt: string) {\n\tif (str.match(/^\\s*$/)) {\n\t\treturn dflt\n\t}\n\treturn str\n}\n\n/** @public */\nexport class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {\n\tstatic override type = 'frame' as const\n\tstatic override props = frameShapeProps\n\tstatic override migrations = frameShapeMigrations\n\n\toverride options: FrameShapeOptions = {\n\t\tshowColors: false,\n\t}\n\n\t// evil crimes :)\n\t// By default, showColors is off. Because they use style props, which are picked up\n\t// automatically, we don't have DefaultColorStyle in the props in the schema by default.\n\t// Instead, when someone calls .configure to turn the option on, we manually add in the color\n\t// style here so it plays nicely with the other editor APIs.\n\tstatic override configure<T extends TLShapeUtilConstructor<any, any>>(\n\t\tthis: T,\n\t\toptions: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never\n\t): T {\n\t\tconst withOptions = super.configure.call(this, options) as T\n\t\tif ((options as any).showColors) {\n\t\t\t;(withOptions as any).props = { ...withOptions.props, color: DefaultColorStyle }\n\t\t}\n\t\treturn withOptions\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride canResize() {\n\t\treturn true\n\t}\n\n\toverride canResizeChildren() {\n\t\treturn false\n\t}\n\n\toverride getDefaultProps(): TLFrameShape['props'] {\n\t\treturn { w: 160 * 2, h: 90 * 2, name: '', color: 'black' }\n\t}\n\n\toverride getAriaDescriptor(shape: TLFrameShape) {\n\t\treturn shape.props.name\n\t}\n\n\toverride getGeometry(shape: TLFrameShape): Geometry2d {\n\t\tconst { editor } = this\n\n\t\tconst z = editor.getZoomLevel()\n\n\t\t// Which dimension measures the top edge after rotation?\n\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\n\t\t// Get the size of the heading (max width equal to the rotatedTopEdgeWidth)\n\t\tconst opts = getFrameHeadingOpts(rotatedTopEdgeWidth, false)\n\t\tconst headingSize = getFrameHeadingSize(editor, shape, opts)\n\n\t\t// If NOT showing frame colors, we need to offset the label\n\t\t// to the left so that the title is in line with the shape edge\n\t\t// and add that extra width to the right side of the label\n\t\tconst isShowingFrameColors = this.options.showColors\n\n\t\t// Scale everything into **screen space**\n\t\tconst extraWidth = FRAME_HEADING_EXTRA_WIDTH / z\n\t\tconst minWidth = FRAME_HEADING_MIN_WIDTH / z\n\t\tconst maxWidth = rotatedTopEdgeWidth + (isShowingFrameColors ? 1 : extraWidth)\n\n\t\tconst labelWidth = headingSize.w / z\n\t\tconst labelHeight = headingSize.h / z\n\n\t\tconst clampedLabelWidth = clamp(labelWidth + extraWidth, minWidth, maxWidth)\n\n\t\tconst offsetX = (isShowingFrameColors ? -1 : FRAME_HEADING_NOCOLORS_OFFSET_X) / z\n\t\tconst offsetY = FRAME_HEADING_OFFSET_Y / z\n\n\t\t// In page space\n\t\tconst width = isVertical ? labelHeight : clampedLabelWidth\n\t\tconst height = isVertical ? clampedLabelWidth : labelHeight\n\n\t\t// Calculate label position based on side. The position needs to always appear\n\t\t// at the top left of the shape, regardless of rotation. The label must be\n\t\t// between a minimum and maximum. The minimum is arbitrary; the maximum is the\n\t\t// width of the edge of the frame where the label will be shown.\n\n\t\tlet x: number, y: number\n\n\t\tswitch (labelSide) {\n\t\t\tcase 0: {\n\t\t\t\t// top\n\t\t\t\tx = offsetX\n\t\t\t\ty = -(labelHeight + offsetY)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 1: {\n\t\t\t\t// right\n\t\t\t\tx = -(labelHeight + offsetY)\n\t\t\t\ty = shape.props.h - (offsetX + clampedLabelWidth)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\t// bottom\n\t\t\t\tx = shape.props.w - (offsetX + clampedLabelWidth)\n\t\t\t\ty = shape.props.h + offsetY\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\t// left\n\t\t\t\tx = shape.props.w + offsetY\n\t\t\t\ty = offsetX\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tisFilled: false,\n\t\t\t\t}),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getText(shape: TLFrameShape): string | undefined {\n\t\treturn shape.props.name\n\t}\n\n\toverride component(shape: TLFrameShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst theme = useDefaultColorTheme()\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst isCreating = useValue(\n\t\t\t'is creating this shape',\n\t\t\t() => {\n\t\t\t\tconst resizingState = this.editor.getStateDescendant('select.resizing')\n\t\t\t\tif (!resizingState) return false\n\t\t\t\tif (!resizingState.getIsActive()) return false\n\t\t\t\tconst info = (resizingState as typeof resizingState & { info: { isCreating: boolean } })\n\t\t\t\t\t?.info\n\t\t\t\tif (!info) return false\n\t\t\t\treturn info.isCreating && this.editor.getOnlySelectedShapeId() === shape.id\n\t\t\t},\n\t\t\t[shape.id]\n\t\t)\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst zoomLevel = useValue('zoom level', () => this.editor.getZoomLevel(), [this.editor])\n\n\t\tconst showFrameColors = this.options.showColors\n\n\t\tconst color = theme[shape.props.color]\n\t\tconst frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill\n\t\tconst frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke\n\t\tconst frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background\n\t\tconst frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background\n\t\tconst frameHeadingText = showFrameColors ? color.frame.text : theme.text\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<SVGContainer>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tclassName={classNames('tl-frame__body', { 'tl-frame__creating': isCreating })}\n\t\t\t\t\t\twidth={shape.props.w + 1 / zoomLevel}\n\t\t\t\t\t\theight={shape.props.h + 1 / zoomLevel}\n\t\t\t\t\t\tfill={frameFill}\n\t\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\t\ty={-0.5 / zoomLevel}\n\t\t\t\t\t\tx={-0.5 / zoomLevel}\n\t\t\t\t\t/>\n\t\t\t\t</SVGContainer>\n\t\t\t\t{isCreating ? null : (\n\t\t\t\t\t<FrameHeading\n\t\t\t\t\t\tid={shape.id}\n\t\t\t\t\t\tname={shape.props.name}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\tcolor={frameHeadingText}\n\t\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\t\toffsetX={showFrameColors ? -1 : -7}\n\t\t\t\t\t\tshowColors={this.options.showColors}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLFrameShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\n\t\t// rotate right 45 deg\n\t\tconst labelSide = getFrameHeadingSide(this.editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\t\tconst labelTranslate = getFrameHeadingTranslation(shape, labelSide, true)\n\n\t\t// Truncate with ellipsis\n\t\tconst opts: TLCreateTextJsxFromSpansOpts = getFrameHeadingOpts(rotatedTopEdgeWidth - 12, true)\n\n\t\tconst frameTitle = defaultEmptyAs(shape.props.name, 'Frame') + String.fromCharCode(8203)\n\t\tconst labelBounds = getFrameHeadingSize(this.editor, shape, opts)\n\t\tconst spans = this.editor.textMeasure.measureTextSpans(frameTitle, opts)\n\t\tconst text = createTextJsxFromSpans(this.editor, spans, opts)\n\n\t\tconst showFrameColors = this.options.showColors\n\n\t\tconst color = theme[shape.props.color]\n\t\tconst frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill\n\t\tconst frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke\n\t\tconst frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background\n\t\tconst frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background\n\t\tconst frameHeadingText = showFrameColors ? color.frame.text : theme.text\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect\n\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\tfill={frameFill}\n\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\tx={0}\n\t\t\t\t\trx={0}\n\t\t\t\t\try={0}\n\t\t\t\t/>\n\t\t\t\t<g fill={frameHeadingText} transform={labelTranslate}>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx={labelBounds.x - (showFrameColors ? 0 : 6)}\n\t\t\t\t\t\ty={labelBounds.y - 6}\n\t\t\t\t\t\twidth={Math.min(rotatedTopEdgeWidth, labelBounds.width + 12)}\n\t\t\t\t\t\theight={labelBounds.height}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\trx={4}\n\t\t\t\t\t\try={4}\n\t\t\t\t\t/>\n\t\t\t\t\t<g transform={`translate(${showFrameColors ? 8 : 0}, 4)`}>{text}</g>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLFrameShape) {\n\t\treturn (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\tclassName={`tl-frame-indicator`}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride providesBackgroundForChildren(): boolean {\n\t\treturn true\n\t}\n\n\toverride canReceiveNewChildrenOfType(shape: TLShape) {\n\t\treturn !shape.isLocked\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLFrameShape,\n\t\tendShape: TLFrameShape,\n\t\tt: number\n\t): TLFrameShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n\n\toverride onDoubleClickEdge(shape: TLFrameShape, info: TLClickEventInfo) {\n\t\tif (info.target !== 'selection') return\n\t\tconst { handle } = info\n\n\t\t// If handle is missing, we can't determine which edge was clicked\n\t\tif (!handle) return\n\n\t\tconst isHorizontalEdge = handle === 'left' || handle === 'right'\n\t\tconst isVerticalEdge = handle === 'top' || handle === 'bottom'\n\n\t\tconst childIds = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tconst children = compact(childIds.map((id) => this.editor.getShape(id)))\n\t\tif (!children.length) return\n\n\t\tconst { dx, dy, w, h } = getFrameChildrenBounds(children, this.editor, { padding: 10 })\n\n\t\tthis.editor.run(() => {\n\t\t\tconst changes: TLShapePartial[] = childIds.map((childId) => {\n\t\t\t\tconst childShape = this.editor.getShape(childId)!\n\t\t\t\treturn {\n\t\t\t\t\tid: childShape.id,\n\t\t\t\t\ttype: childShape.type,\n\t\t\t\t\tx: isHorizontalEdge ? childShape.x + dx : childShape.x,\n\t\t\t\t\ty: isVerticalEdge ? childShape.y + dy : childShape.y,\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tthis.editor.updateShapes(changes)\n\t\t})\n\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: {\n\t\t\t\tw: isHorizontalEdge ? w : shape.props.w,\n\t\t\t\th: isVerticalEdge ? h : shape.props.h,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onDoubleClickCorner(shape: TLFrameShape) {\n\t\tfitFrameToContent(this.editor, shape.id, { padding: 10 })\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t}\n\t}\n\n\toverride onDragShapesIn(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\t{ initialParentIds, initialIndices }: TLDragShapesOverInfo\n\t) {\n\t\tconst { editor } = this\n\n\t\tif (draggingShapes.every((s) => s.parentId === shape.id)) return\n\n\t\t// Check to see whether any of the shapes can have their old index restored\n\t\tlet canRestoreOriginalIndices = false\n\t\tconst previousChildren = draggingShapes.filter((s) => shape.id === initialParentIds.get(s.id))\n\n\t\tif (previousChildren.length > 0) {\n\t\t\tconst currentChildren = compact(\n\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t)\n\t\t\tif (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {\n\t\t\t\tcanRestoreOriginalIndices = true\n\t\t\t}\n\t\t}\n\n\t\t// I can't imagine this happening, but if any of the children are the ancestor of the frame, quit here\n\t\tif (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return\n\n\t\t// Reparent the shapes to the new parent\n\t\teditor.reparentShapes(draggingShapes, shape.id)\n\n\t\t// If we can restore the original indices, then do so\n\t\tif (canRestoreOriginalIndices) {\n\t\t\tfor (const shape of previousChildren) {\n\t\t\t\teditor.updateShape({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tindex: initialIndices.get(shape.id),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onDragShapesOut(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\tinfo: TLDragShapesOutInfo\n\t): void {\n\t\tconst { editor } = this\n\t\t// When a user drags shapes out of a frame, and if we're not dragging into a new shape, then reparent\n\t\t// the dragging shapes (that are current children of the frame) onto the current page instead\n\t\tif (!info.nextDraggingOverShapeId) {\n\t\t\teditor.reparentShapes(\n\t\t\t\tdraggingShapes.filter(\n\t\t\t\t\t(s) => s.parentId === shape.id && this.canReceiveNewChildrenOfType(s)\n\t\t\t\t),\n\t\t\t\teditor.getCurrentPageId()\n\t\t\t)\n\t\t}\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tDefaultColorStyle,\n\tGeometry2d,\n\tGroup2d,\n\tRectangle2d,\n\tSVGContainer,\n\tSvgExportContext,\n\tTLClickEventInfo,\n\tTLDragShapesOutInfo,\n\tTLDragShapesOverInfo,\n\tTLFrameShape,\n\tTLFrameShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLShapeUtilConstructor,\n\tclamp,\n\tcompact,\n\tframeShapeMigrations,\n\tframeShapeProps,\n\tgetDefaultColorTheme,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { fitFrameToContent, getFrameChildrenBounds } from '../../utils/frames/frames'\nimport {\n\tTLCreateTextJsxFromSpansOpts,\n\tcreateTextJsxFromSpans,\n} from '../shared/createTextJsxFromSpans'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { FrameHeading } from './components/FrameHeading'\nimport {\n\tgetFrameHeadingOpts,\n\tgetFrameHeadingSide,\n\tgetFrameHeadingSize,\n\tgetFrameHeadingTranslation,\n} from './frameHelpers'\n\n// Some of these values are repeated in CSS and need to match\nconst FRAME_HEADING_EXTRA_WIDTH = 12\nconst FRAME_HEADING_MIN_WIDTH = 32\nconst FRAME_HEADING_NOCOLORS_OFFSET_X = -7\nconst FRAME_HEADING_OFFSET_Y = 4\n\n/** @public */\nexport interface FrameShapeOptions {\n\t/**\n\t * When true, the frame will display colors for the shape's headings and background.\n\t */\n\tshowColors: boolean\n}\n\nexport function defaultEmptyAs(str: string, dflt: string) {\n\tif (str.match(/^\\s*$/)) {\n\t\treturn dflt\n\t}\n\treturn str\n}\n\n/** @public */\nexport class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {\n\tstatic override type = 'frame' as const\n\tstatic override props = frameShapeProps\n\tstatic override migrations = frameShapeMigrations\n\n\toverride options: FrameShapeOptions = {\n\t\tshowColors: false,\n\t}\n\n\t// evil crimes :)\n\t// By default, showColors is off. Because they use style props, which are picked up\n\t// automatically, we don't have DefaultColorStyle in the props in the schema by default.\n\t// Instead, when someone calls .configure to turn the option on, we manually add in the color\n\t// style here so it plays nicely with the other editor APIs.\n\tstatic override configure<T extends TLShapeUtilConstructor<any, any>>(\n\t\tthis: T,\n\t\toptions: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never\n\t): T {\n\t\tconst withOptions = super.configure.call(this, options) as T\n\t\tif ((options as any).showColors) {\n\t\t\t;(withOptions as any).props = { ...withOptions.props, color: DefaultColorStyle }\n\t\t}\n\t\treturn withOptions\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride canResize() {\n\t\treturn true\n\t}\n\n\toverride canResizeChildren() {\n\t\treturn false\n\t}\n\n\toverride getDefaultProps(): TLFrameShape['props'] {\n\t\treturn { w: 160 * 2, h: 90 * 2, name: '', color: 'black' }\n\t}\n\n\toverride getAriaDescriptor(shape: TLFrameShape) {\n\t\treturn shape.props.name\n\t}\n\n\toverride getGeometry(shape: TLFrameShape): Geometry2d {\n\t\tconst { editor } = this\n\n\t\tconst z = editor.getZoomLevel()\n\n\t\t// Which dimension measures the top edge after rotation?\n\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\n\t\t// Get the size of the heading (max width equal to the rotatedTopEdgeWidth)\n\t\tconst opts = getFrameHeadingOpts(rotatedTopEdgeWidth, false)\n\t\tconst headingSize = getFrameHeadingSize(editor, shape, opts)\n\n\t\t// If NOT showing frame colors, we need to offset the label\n\t\t// to the left so that the title is in line with the shape edge\n\t\t// and add that extra width to the right side of the label\n\t\tconst isShowingFrameColors = this.options.showColors\n\n\t\t// Scale everything into **screen space**\n\t\tconst extraWidth = FRAME_HEADING_EXTRA_WIDTH / z\n\t\tconst minWidth = FRAME_HEADING_MIN_WIDTH / z\n\t\tconst maxWidth = rotatedTopEdgeWidth + (isShowingFrameColors ? 1 : extraWidth)\n\n\t\tconst labelWidth = headingSize.w / z\n\t\tconst labelHeight = headingSize.h / z\n\n\t\tconst clampedLabelWidth = clamp(labelWidth + extraWidth, minWidth, maxWidth)\n\n\t\tconst offsetX = (isShowingFrameColors ? -1 : FRAME_HEADING_NOCOLORS_OFFSET_X) / z\n\t\tconst offsetY = FRAME_HEADING_OFFSET_Y / z\n\n\t\t// In page space\n\t\tconst width = isVertical ? labelHeight : clampedLabelWidth\n\t\tconst height = isVertical ? clampedLabelWidth : labelHeight\n\n\t\t// Calculate label position based on side. The position needs to always appear\n\t\t// at the top left of the shape, regardless of rotation. The label must be\n\t\t// between a minimum and maximum. The minimum is arbitrary; the maximum is the\n\t\t// width of the edge of the frame where the label will be shown.\n\n\t\tlet x: number, y: number\n\n\t\tswitch (labelSide) {\n\t\t\tcase 0: {\n\t\t\t\t// top\n\t\t\t\tx = offsetX\n\t\t\t\ty = -(labelHeight + offsetY)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 1: {\n\t\t\t\t// right\n\t\t\t\tx = -(labelHeight + offsetY)\n\t\t\t\ty = shape.props.h - (offsetX + clampedLabelWidth)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\t// bottom\n\t\t\t\tx = shape.props.w - (offsetX + clampedLabelWidth)\n\t\t\t\ty = shape.props.h + offsetY\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\t// left\n\t\t\t\tx = shape.props.w + offsetY\n\t\t\t\ty = offsetX\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tisFilled: false,\n\t\t\t\t}),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getText(shape: TLFrameShape): string | undefined {\n\t\treturn shape.props.name\n\t}\n\n\toverride component(shape: TLFrameShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst theme = useDefaultColorTheme()\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst isCreating = useValue(\n\t\t\t'is creating this shape',\n\t\t\t() => {\n\t\t\t\tconst resizingState = this.editor.getStateDescendant('select.resizing')\n\t\t\t\tif (!resizingState) return false\n\t\t\t\tif (!resizingState.getIsActive()) return false\n\t\t\t\tconst info = (resizingState as typeof resizingState & { info: { isCreating: boolean } })\n\t\t\t\t\t?.info\n\t\t\t\tif (!info) return false\n\t\t\t\treturn info.isCreating && this.editor.getOnlySelectedShapeId() === shape.id\n\t\t\t},\n\t\t\t[shape.id]\n\t\t)\n\n\t\tconst showFrameColors = this.options.showColors\n\n\t\tconst color = theme[shape.props.color]\n\t\tconst frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill\n\t\tconst frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke\n\t\tconst frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background\n\t\tconst frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background\n\t\tconst frameHeadingText = showFrameColors ? color.frame.text : theme.text\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<SVGContainer>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tclassName={classNames('tl-frame__body', { 'tl-frame__creating': isCreating })}\n\t\t\t\t\t\tfill={frameFill}\n\t\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\twidth: `calc(${shape.props.w}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\theight: `calc(${shape.props.h}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\ttransform: `translate(calc(-0.5px / var(--tl-zoom)), calc(-0.5px / var(--tl-zoom)))`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</SVGContainer>\n\t\t\t\t{isCreating ? null : (\n\t\t\t\t\t<FrameHeading\n\t\t\t\t\t\tid={shape.id}\n\t\t\t\t\t\tname={shape.props.name}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\tcolor={frameHeadingText}\n\t\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\t\toffsetX={showFrameColors ? -1 : -7}\n\t\t\t\t\t\tshowColors={this.options.showColors}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLFrameShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\n\t\t// rotate right 45 deg\n\t\tconst labelSide = getFrameHeadingSide(this.editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\t\tconst labelTranslate = getFrameHeadingTranslation(shape, labelSide, true)\n\n\t\t// Truncate with ellipsis\n\t\tconst opts: TLCreateTextJsxFromSpansOpts = getFrameHeadingOpts(rotatedTopEdgeWidth - 12, true)\n\n\t\tconst frameTitle = defaultEmptyAs(shape.props.name, 'Frame') + String.fromCharCode(8203)\n\t\tconst labelBounds = getFrameHeadingSize(this.editor, shape, opts)\n\t\tconst spans = this.editor.textMeasure.measureTextSpans(frameTitle, opts)\n\t\tconst text = createTextJsxFromSpans(this.editor, spans, opts)\n\n\t\tconst showFrameColors = this.options.showColors\n\n\t\tconst color = theme[shape.props.color]\n\t\tconst frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill\n\t\tconst frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke\n\t\tconst frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background\n\t\tconst frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background\n\t\tconst frameHeadingText = showFrameColors ? color.frame.text : theme.text\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect\n\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\tfill={frameFill}\n\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\tx={0}\n\t\t\t\t\trx={0}\n\t\t\t\t\try={0}\n\t\t\t\t/>\n\t\t\t\t<g fill={frameHeadingText} transform={labelTranslate}>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx={labelBounds.x - (showFrameColors ? 0 : 6)}\n\t\t\t\t\t\ty={labelBounds.y - 6}\n\t\t\t\t\t\twidth={Math.min(rotatedTopEdgeWidth, labelBounds.width + 12)}\n\t\t\t\t\t\theight={labelBounds.height}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\trx={4}\n\t\t\t\t\t\try={4}\n\t\t\t\t\t/>\n\t\t\t\t\t<g transform={`translate(${showFrameColors ? 8 : 0}, 4)`}>{text}</g>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLFrameShape) {\n\t\treturn (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\tclassName={`tl-frame-indicator`}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride providesBackgroundForChildren(): boolean {\n\t\treturn true\n\t}\n\n\toverride canReceiveNewChildrenOfType(shape: TLShape) {\n\t\treturn !shape.isLocked\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLFrameShape,\n\t\tendShape: TLFrameShape,\n\t\tt: number\n\t): TLFrameShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n\n\toverride onDoubleClickEdge(shape: TLFrameShape, info: TLClickEventInfo) {\n\t\tif (info.target !== 'selection') return\n\t\tconst { handle } = info\n\n\t\t// If handle is missing, we can't determine which edge was clicked\n\t\tif (!handle) return\n\n\t\tconst isHorizontalEdge = handle === 'left' || handle === 'right'\n\t\tconst isVerticalEdge = handle === 'top' || handle === 'bottom'\n\n\t\tconst childIds = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tconst children = compact(childIds.map((id) => this.editor.getShape(id)))\n\t\tif (!children.length) return\n\n\t\tconst { dx, dy, w, h } = getFrameChildrenBounds(children, this.editor, { padding: 10 })\n\n\t\tthis.editor.run(() => {\n\t\t\tconst changes: TLShapePartial[] = childIds.map((childId) => {\n\t\t\t\tconst childShape = this.editor.getShape(childId)!\n\t\t\t\treturn {\n\t\t\t\t\tid: childShape.id,\n\t\t\t\t\ttype: childShape.type,\n\t\t\t\t\tx: isHorizontalEdge ? childShape.x + dx : childShape.x,\n\t\t\t\t\ty: isVerticalEdge ? childShape.y + dy : childShape.y,\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tthis.editor.updateShapes(changes)\n\t\t})\n\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: {\n\t\t\t\tw: isHorizontalEdge ? w : shape.props.w,\n\t\t\t\th: isVerticalEdge ? h : shape.props.h,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onDoubleClickCorner(shape: TLFrameShape) {\n\t\tfitFrameToContent(this.editor, shape.id, { padding: 10 })\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t}\n\t}\n\n\toverride onDragShapesIn(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\t{ initialParentIds, initialIndices }: TLDragShapesOverInfo\n\t) {\n\t\tconst { editor } = this\n\n\t\tif (draggingShapes.every((s) => s.parentId === shape.id)) return\n\n\t\t// Check to see whether any of the shapes can have their old index restored\n\t\tlet canRestoreOriginalIndices = false\n\t\tconst previousChildren = draggingShapes.filter((s) => shape.id === initialParentIds.get(s.id))\n\n\t\tif (previousChildren.length > 0) {\n\t\t\tconst currentChildren = compact(\n\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t)\n\t\t\tif (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {\n\t\t\t\tcanRestoreOriginalIndices = true\n\t\t\t}\n\t\t}\n\n\t\t// I can't imagine this happening, but if any of the children are the ancestor of the frame, quit here\n\t\tif (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return\n\n\t\t// Reparent the shapes to the new parent\n\t\teditor.reparentShapes(draggingShapes, shape.id)\n\n\t\t// If we can restore the original indices, then do so\n\t\tif (canRestoreOriginalIndices) {\n\t\t\tfor (const shape of previousChildren) {\n\t\t\t\teditor.updateShape({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tindex: initialIndices.get(shape.id),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onDragShapesOut(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\tinfo: TLDragShapesOutInfo\n\t): void {\n\t\tconst { editor } = this\n\t\t// When a user drags shapes out of a frame, and if we're not dragging into a new shape, then reparent\n\t\t// the dragging shapes (that are current children of the frame) onto the current page instead\n\t\tif (!info.nextDraggingOverShapeId) {\n\t\t\teditor.reparentShapes(\n\t\t\t\tdraggingShapes.filter(\n\t\t\t\t\t(s) => s.parentId === shape.id && this.canReceiveNewChildrenOfType(s)\n\t\t\t\t),\n\t\t\t\teditor.getCurrentPageId()\n\t\t\t)\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["classNames", "shape"]
|
|
7
7
|
}
|
|
@@ -127,7 +127,6 @@ class LineShapeUtil extends import_editor.ShapeUtil {
|
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
onHandleDrag(shape, { handle }) {
|
|
130
|
-
if (handle.type !== "vertex") return;
|
|
131
130
|
const newPoint = (0, import_editor.maybeSnapToGrid)(new import_editor.Vec(handle.x, handle.y), this.editor);
|
|
132
131
|
return {
|
|
133
132
|
...shape,
|
|
@@ -140,6 +139,21 @@ class LineShapeUtil extends import_editor.ShapeUtil {
|
|
|
140
139
|
}
|
|
141
140
|
};
|
|
142
141
|
}
|
|
142
|
+
onHandleDragStart(shape, { handle }) {
|
|
143
|
+
if (handle.type === "create") {
|
|
144
|
+
return {
|
|
145
|
+
...shape,
|
|
146
|
+
props: {
|
|
147
|
+
...shape.props,
|
|
148
|
+
points: {
|
|
149
|
+
...shape.props.points,
|
|
150
|
+
[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
143
157
|
component(shape) {
|
|
144
158
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_editor.SVGContainer, { style: { minWidth: 50, minHeight: 50 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LineShapeSvg, { shape }) });
|
|
145
159
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/line/LineShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n} from '@tldraw/editor'\n\nimport { STROKE_SIZES } from '../arrow/shared'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride hideResizeHandles() {\n\t\treturn true\n\t}\n\toverride hideRotateHandle() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\tid: point.index,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n} from '@tldraw/editor'\n\nimport { STROKE_SIZES } from '../arrow/shared'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride hideResizeHandles() {\n\t\treturn true\n\t}\n\toverride hideRotateHandle() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\tid: point.index,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\tconst newPoint = maybeSnapToGrid(new Vec(handle.x, handle.y), this.editor)\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tpoints: {\n\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t[handle.id]: { id: handle.id, index: handle.index, x: newPoint.x, y: newPoint.y },\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onHandleDragStart(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t// For line shapes, if we're dragging a \"create\" handle, then\n\t\t// create a new vertex handle at that point; and make this handle\n\t\t// the handle that we're dragging.\n\t\tif (handle.type === 'create') {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tpoints: {\n\t\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t\t[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\tcomponent(shape: TLLineShape) {\n\t\treturn (\n\t\t\t<SVGContainer style={{ minWidth: 50, minHeight: 50 }}>\n\t\t\t\t<LineShapeSvg shape={shape} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLLineShape) {\n\t\tconst strokeWidth = STROKE_SIZES[shape.props.size] * shape.props.scale\n\t\tconst path = getPathForLineShape(shape)\n\t\tconst { dash } = shape.props\n\n\t\treturn path.toSvg({\n\t\t\tstyle: dash === 'draw' ? 'draw' : 'solid',\n\t\t\tstrokeWidth: 1,\n\t\t\tpasses: 1,\n\t\t\trandomSeed: shape.id,\n\t\t\toffset: 0,\n\t\t\troundness: strokeWidth * 2,\n\t\t\tprops: { strokeWidth: undefined },\n\t\t})\n\t}\n\n\toverride toSvg(shape: TLLineShape) {\n\t\treturn <LineShapeSvg shouldScale shape={shape} />\n\t}\n\n\toverride getHandleSnapGeometry(shape: TLLineShape): HandleSnapGeometry {\n\t\tconst points = linePointsToArray(shape)\n\t\treturn {\n\t\t\tpoints,\n\t\t\tgetSelfSnapPoints: (handle) => {\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// We want to skip the current and adjacent handles\n\t\t\t\treturn points.filter((_, i) => Math.abs(i - index) > 1).map(Vec.From)\n\t\t\t},\n\t\t\tgetSelfSnapOutline: (handle) => {\n\t\t\t\t// We want to skip the segments that include the handle, so\n\t\t\t\t// find the index of the handle that shares the same index property\n\t\t\t\t// as the initial dragging handle; this catches a quirk of create handles\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// Get all the outline segments from the shape that don't include the handle\n\t\t\t\tconst segments = this.getGeometry(shape)\n\t\t\t\t\t.getSegments()\n\t\t\t\t\t.filter((_, i) => i !== index - 1 && i !== index)\n\n\t\t\t\tif (!segments.length) return null\n\t\t\t\treturn new Group2d({ children: segments })\n\t\t\t},\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLLineShape,\n\t\tendShape: TLLineShape,\n\t\tt: number\n\t): TLLineShape['props'] {\n\t\tconst startPoints = linePointsToArray(startShape)\n\t\tconst endPoints = linePointsToArray(endShape)\n\n\t\tconst pointsToUseStart: TLLineShapePoint[] = []\n\t\tconst pointsToUseEnd: TLLineShapePoint[] = []\n\n\t\tlet index = ZERO_INDEX_KEY\n\n\t\tif (startPoints.length > endPoints.length) {\n\t\t\t// we'll need to expand points\n\t\t\tfor (let i = 0; i < startPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = { ...startPoints[i] }\n\t\t\t\tif (endPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[endPoints.length - 1], id: index }\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else if (endPoints.length > startPoints.length) {\n\t\t\t// we'll need to converge points\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i] }\n\t\t\t\tif (startPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseStart[i] = {\n\t\t\t\t\t\t...startPoints[startPoints.length - 1],\n\t\t\t\t\t\tid: index,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseStart[i] = { ...startPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else {\n\t\t\t// noop, easy\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = startPoints[i]\n\t\t\t\tpointsToUseEnd[i] = endPoints[i]\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tpoints: Object.fromEntries(\n\t\t\t\tpointsToUseStart.map((point, i) => {\n\t\t\t\t\tconst endPoint = pointsToUseEnd[i]\n\t\t\t\t\treturn [\n\t\t\t\t\t\tpoint.id,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...point,\n\t\t\t\t\t\t\tx: lerp(point.x, endPoint.x, t),\n\t\t\t\t\t\t\ty: lerp(point.y, endPoint.y, t),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction linePointsToArray(shape: TLLineShape) {\n\treturn Object.values(shape.props.points).sort(sortByIndex)\n}\n\nconst pathCache = new WeakCache<TLLineShape, PathBuilder>()\nfunction getPathForLineShape(shape: TLLineShape): PathBuilder {\n\treturn pathCache.get(shape, () => {\n\t\tconst points = linePointsToArray(shape).map(Vec.From)\n\n\t\tswitch (shape.props.spline) {\n\t\t\tcase 'cubic': {\n\t\t\t\treturn PathBuilder.cubicSplineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\treturn PathBuilder.lineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction LineShapeSvg({\n\tshape,\n\tshouldScale = false,\n\tforceSolid = false,\n}: {\n\tshape: TLLineShape\n\tshouldScale?: boolean\n\tforceSolid?: boolean\n}) {\n\tconst theme = useDefaultColorTheme()\n\n\tconst path = getPathForLineShape(shape)\n\tconst { dash, color, size } = shape.props\n\n\tconst scaleFactor = 1 / shape.props.scale\n\n\tconst scale = shouldScale ? scaleFactor : 1\n\n\tconst strokeWidth = STROKE_SIZES[size] * shape.props.scale\n\n\treturn path.toSvg({\n\t\tstyle: dash,\n\t\tstrokeWidth,\n\t\tforceSolid,\n\t\trandomSeed: shape.id,\n\t\tprops: { transform: `scale(${scale})`, stroke: theme[color].solid, fill: 'none' },\n\t})\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -135,7 +135,11 @@ class PathBuilder {
|
|
|
135
135
|
endAngle += 2 * Math.PI;
|
|
136
136
|
}
|
|
137
137
|
const sweepAngle = endAngle - startAngle;
|
|
138
|
+
const approximateArcLength = Math.max(rx1, ry1) * Math.abs(sweepAngle);
|
|
138
139
|
const numSegments = Math.min(4, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2)));
|
|
140
|
+
const resolutionPerSegment = Math.ceil(
|
|
141
|
+
(0, import_editor.getVerticesCountForArcLength)(approximateArcLength) / numSegments
|
|
142
|
+
);
|
|
139
143
|
const anglePerSegment = sweepAngle / numSegments;
|
|
140
144
|
const ellipsePoint = (angle) => {
|
|
141
145
|
return {
|
|
@@ -163,11 +167,23 @@ class PathBuilder {
|
|
|
163
167
|
const cp2x = end.x - handleScale * d2.x;
|
|
164
168
|
const cp2y = end.y - handleScale * d2.y;
|
|
165
169
|
const bezierOpts = i === 0 ? opts : { ...opts, mergeWithPrevious: true };
|
|
166
|
-
this.
|
|
170
|
+
this.cubicBezierToWithResolution(
|
|
171
|
+
end.x,
|
|
172
|
+
end.y,
|
|
173
|
+
cp1x,
|
|
174
|
+
cp1y,
|
|
175
|
+
cp2x,
|
|
176
|
+
cp2y,
|
|
177
|
+
bezierOpts,
|
|
178
|
+
resolutionPerSegment
|
|
179
|
+
);
|
|
167
180
|
}
|
|
168
181
|
return this;
|
|
169
182
|
}
|
|
170
183
|
cubicBezierTo(x, y, cp1X, cp1Y, cp2X, cp2Y, opts) {
|
|
184
|
+
return this.cubicBezierToWithResolution(x, y, cp1X, cp1Y, cp2X, cp2Y, opts);
|
|
185
|
+
}
|
|
186
|
+
cubicBezierToWithResolution(x, y, cp1X, cp1Y, cp2X, cp2Y, opts, resolution) {
|
|
171
187
|
this.assertHasMoveTo();
|
|
172
188
|
this.commands.push({
|
|
173
189
|
type: "cubic",
|
|
@@ -176,7 +192,8 @@ class PathBuilder {
|
|
|
176
192
|
cp1: { x: cp1X, y: cp1Y },
|
|
177
193
|
cp2: { x: cp2X, y: cp2Y },
|
|
178
194
|
isClose: false,
|
|
179
|
-
opts
|
|
195
|
+
opts,
|
|
196
|
+
resolution
|
|
180
197
|
});
|
|
181
198
|
return this;
|
|
182
199
|
}
|
|
@@ -639,7 +656,8 @@ class PathBuilderGeometry2d extends import_editor.Geometry2d {
|
|
|
639
656
|
start: import_editor.Vec.From(last),
|
|
640
657
|
cp1: import_editor.Vec.From(command.cp1),
|
|
641
658
|
cp2: import_editor.Vec.From(command.cp2),
|
|
642
|
-
end: import_editor.Vec.From(command)
|
|
659
|
+
end: import_editor.Vec.From(command),
|
|
660
|
+
resolution: command.resolution
|
|
643
661
|
})
|
|
644
662
|
);
|
|
645
663
|
break;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/PathBuilder.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tapproximately,\n\tassert,\n\tassertExists,\n\tclamp,\n\tCubicBezier2d,\n\tEdge2d,\n\texhaustiveSwitchError,\n\tGeometry2d,\n\tGeometry2dFilters,\n\tGeometry2dOptions,\n\tgetPerfectDashProps,\n\tGroup2d,\n\tmodulate,\n\tPerfectDashTerminal,\n\trng,\n\ttoDomPrecision,\n\tVec,\n\tVecLike,\n\tVecModel,\n} from '@tldraw/editor'\nimport { ReactNode, SVGProps } from 'react'\n\n/** @public */\nexport interface BasePathBuilderOpts {\n\tstrokeWidth: number\n\tforceSolid?: boolean\n\tonlyFilled?: boolean\n\tprops?: SVGProps<SVGPathElement & SVGGElement>\n}\n\n/** @public */\nexport interface SolidPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'solid'\n}\n\n/** @public */\nexport interface DashedPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'dashed' | 'dotted'\n\tsnap?: number\n\tend?: PerfectDashTerminal\n\tstart?: PerfectDashTerminal\n\tlengthRatio?: number\n}\n\n/** @public */\nexport interface DrawPathBuilderDOpts {\n\tstrokeWidth: number\n\trandomSeed: string\n\toffset?: number\n\troundness?: number\n\tpasses?: number\n\tonlyFilled?: boolean\n}\n\n/** @public */\nexport interface DrawPathBuilderOpts extends BasePathBuilderOpts, DrawPathBuilderDOpts {\n\tstyle: 'draw'\n}\n\n/** @public */\nexport type PathBuilderOpts = SolidPathBuilderOpts | DashedPathBuilderOpts | DrawPathBuilderOpts\n\n/** @public */\nexport interface PathBuilderCommandOpts {\n\t/**\n\t * When converting to a draw-style line, how much offset from the original point should be\n\t * applied?\n\t */\n\toffset?: number\n\t/**\n\t * When converting to a draw-style line, how much roundness should be applied to the end of this\n\t * line?\n\t */\n\troundness?: number\n\t/**\n\t * When converting to a dash- or dot-style line, should the current segment be merged with the\n\t * previous segment when calculating the dash pattern? This is false by default, meaning each\n\t * command will start/end on a dash/dot boundary.\n\t */\n\tmergeWithPrevious?: boolean\n}\n\n/** @internal */\nexport interface PathBuilderCommandInfo {\n\ttangentStart: VecModel\n\ttangentEnd: VecModel\n\tlength: number\n}\n\n/** @internal */\nexport interface PathBuilderCommandBase {\n\topts?: PathBuilderCommandOpts\n\tx: number\n\ty: number\n\tisClose: boolean\n\t_info?: PathBuilderCommandInfo\n}\n\n/** @public */\nexport interface PathBuilderLineOpts extends PathBuilderCommandOpts {\n\tgeometry?: Omit<Geometry2dOptions, 'isClosed'> | false\n\tdashStart?: PerfectDashTerminal\n\tdashEnd?: PerfectDashTerminal\n}\n\n/** @internal */\nexport interface MoveToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'move'\n\tcloseIdx: number | null\n\topts?: PathBuilderLineOpts\n}\n\n/** @internal */\nexport interface LineToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'line'\n}\n\n/** @internal */\nexport interface CubicBezierToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'cubic'\n\tcp1: VecModel\n\tcp2: VecModel\n}\n\n/** @internal */\nexport type PathBuilderCommand =\n\t| MoveToPathBuilderCommand\n\t| LineToPathBuilderCommand\n\t| CubicBezierToPathBuilderCommand\n\n/** @public */\nexport interface PathBuilderToDOpts {\n\tstartIdx?: number\n\tendIdx?: number\n\tonlyFilled?: boolean\n}\n\n/** @public */\nexport class PathBuilder {\n\tstatic lineThroughPoints(\n\t\tpoints: VecLike[],\n\t\topts?: PathBuilderLineOpts & { endOffsets?: number }\n\t) {\n\t\tconst path = new PathBuilder()\n\t\tpath.moveTo(points[0].x, points[0].y, { ...opts, offset: opts?.endOffsets ?? opts?.offset })\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst isLast = i === points.length - 1\n\t\t\tpath.lineTo(points[i].x, points[i].y, isLast ? { offset: opts?.endOffsets } : undefined)\n\t\t}\n\t\treturn path\n\t}\n\n\tstatic cubicSplineThroughPoints(\n\t\tpoints: VecLike[],\n\t\topts?: PathBuilderLineOpts & { endOffsets?: number }\n\t) {\n\t\tconst path = new PathBuilder()\n\t\tconst len = points.length\n\t\tconst last = len - 2\n\t\tconst k = 1.25\n\n\t\tpath.moveTo(points[0].x, points[0].y, { ...opts, offset: opts?.endOffsets ?? opts?.offset })\n\n\t\tfor (let i = 0; i < len - 1; i++) {\n\t\t\tconst p0 = i === 0 ? points[0] : points[i - 1]\n\t\t\tconst p1 = points[i]\n\t\t\tconst p2 = points[i + 1]\n\t\t\tconst p3 = i === last ? p2 : points[i + 2]\n\n\t\t\tlet cp1x, cp1y, cp2x, cp2y\n\t\t\tif (i === 0) {\n\t\t\t\tcp1x = p0.x\n\t\t\t\tcp1y = p0.y\n\t\t\t} else {\n\t\t\t\tcp1x = p1.x + ((p2.x - p0.x) / 6) * k\n\t\t\t\tcp1y = p1.y + ((p2.y - p0.y) / 6) * k\n\t\t\t}\n\n\t\t\tlet pointOpts = undefined\n\t\t\tif (i === last) {\n\t\t\t\tcp2x = p2.x\n\t\t\t\tcp2y = p2.y\n\t\t\t\tpointOpts = { offset: opts?.endOffsets }\n\t\t\t} else {\n\t\t\t\tcp2x = p2.x - ((p3.x - p1.x) / 6) * k\n\t\t\t\tcp2y = p2.y - ((p3.y - p1.y) / 6) * k\n\t\t\t}\n\n\t\t\tpath.cubicBezierTo(p2.x, p2.y, cp1x, cp1y, cp2x, cp2y, pointOpts)\n\t\t}\n\n\t\treturn path\n\t}\n\n\tconstructor() {}\n\n\t/** @internal */\n\tcommands: PathBuilderCommand[] = []\n\n\tprivate lastMoveTo: MoveToPathBuilderCommand | null = null\n\tprivate assertHasMoveTo() {\n\t\tassert(this.lastMoveTo, 'Start an SVGPathBuilder with `.moveTo()`')\n\t\treturn this.lastMoveTo\n\t}\n\n\tmoveTo(x: number, y: number, opts?: PathBuilderLineOpts) {\n\t\tthis.lastMoveTo = { type: 'move', x, y, closeIdx: null, isClose: false, opts }\n\t\tthis.commands.push(this.lastMoveTo)\n\t\treturn this\n\t}\n\n\tlineTo(x: number, y: number, opts?: PathBuilderCommandOpts) {\n\t\tthis.assertHasMoveTo()\n\t\tthis.commands.push({ type: 'line', x, y, isClose: false, opts })\n\t\treturn this\n\t}\n\n\tcircularArcTo(\n\t\tradius: number,\n\t\tlargeArcFlag: boolean,\n\t\tsweepFlag: boolean,\n\t\tx2: number,\n\t\ty2: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\treturn this.arcTo(radius, radius, largeArcFlag, sweepFlag, 0, x2, y2, opts)\n\t}\n\n\tarcTo(\n\t\trx: number,\n\t\try: number,\n\t\tlargeArcFlag: boolean,\n\t\tsweepFlag: boolean,\n\t\txAxisRotationRadians: number,\n\t\tx2: number,\n\t\ty2: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\t// As arc flags make them very sensitive to offsets when we render them in draw mode, we\n\t\t// approximate arcs by converting them to up to 4 (1 per 90\u00B0 segment) cubic bezier curves.\n\t\t// This algorithm is a Claude special:\n\t\t// https://claude.ai/public/artifacts/5ea0bf18-4afb-4b3d-948d-31b8a77ef1e2\n\n\t\tthis.assertHasMoveTo()\n\n\t\tconst x1 = this.commands[this.commands.length - 1].x\n\t\tconst y1 = this.commands[this.commands.length - 1].y\n\n\t\t// If the endpoints are identical, don't add a command\n\t\tif (x1 === x2 && y1 === y2) {\n\t\t\treturn this\n\t\t}\n\n\t\t// If rx or ry is 0, return a straight line\n\t\tif (rx === 0 || ry === 0) {\n\t\t\treturn this.lineTo(x2, y2, opts)\n\t\t}\n\n\t\t// Convert angle from degrees to radians\n\t\tconst phi = xAxisRotationRadians\n\t\tconst sinPhi = Math.sin(phi)\n\t\tconst cosPhi = Math.cos(phi)\n\n\t\t// Ensure rx and ry are positive\n\t\tlet rx1 = Math.abs(rx)\n\t\tlet ry1 = Math.abs(ry)\n\n\t\t// Step 1: Compute (x1', y1') - transform from ellipse coordinate system to unit circle\n\t\tconst dx = (x1 - x2) / 2\n\t\tconst dy = (y1 - y2) / 2\n\t\tconst x1p = cosPhi * dx + sinPhi * dy\n\t\tconst y1p = -sinPhi * dx + cosPhi * dy\n\n\t\t// Correction of out-of-range radii\n\t\tconst lambda = (x1p * x1p) / (rx1 * rx1) + (y1p * y1p) / (ry1 * ry1)\n\t\tif (lambda > 1) {\n\t\t\tconst sqrtLambda = Math.sqrt(lambda)\n\t\t\trx1 *= sqrtLambda\n\t\t\try1 *= sqrtLambda\n\t\t}\n\n\t\t// Step 2: Compute (cx', cy') - center of ellipse in transformed system\n\t\tconst sign = largeArcFlag !== sweepFlag ? 1 : -1\n\n\t\tconst term = rx1 * rx1 * ry1 * ry1 - rx1 * rx1 * y1p * y1p - ry1 * ry1 * x1p * x1p\n\t\tconst numerator = rx1 * rx1 * y1p * y1p + ry1 * ry1 * x1p * x1p\n\n\t\tlet radicand = term / numerator\n\t\tradicand = radicand < 0 ? 0 : radicand\n\n\t\tconst coef = sign * Math.sqrt(radicand)\n\n\t\tconst cxp = coef * ((rx1 * y1p) / ry1)\n\t\tconst cyp = coef * (-(ry1 * x1p) / rx1)\n\n\t\t// Step 3: Compute (cx, cy) from (cx', cy') - transform back to original coordinate system\n\t\tconst cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2\n\t\tconst cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2\n\n\t\t// Step 4: Compute the start and end angles\n\t\tconst ux = (x1p - cxp) / rx1\n\t\tconst uy = (y1p - cyp) / ry1\n\t\tconst vx = (-x1p - cxp) / rx1\n\t\tconst vy = (-y1p - cyp) / ry1\n\n\t\tconst startAngle = Math.atan2(uy, ux)\n\t\tlet endAngle = Math.atan2(vy, vx)\n\n\t\t// Ensure correct sweep direction\n\t\tif (!sweepFlag && endAngle > startAngle) {\n\t\t\tendAngle -= 2 * Math.PI\n\t\t} else if (sweepFlag && endAngle < startAngle) {\n\t\t\tendAngle += 2 * Math.PI\n\t\t}\n\n\t\t// Calculate the sweep angle\n\t\tconst sweepAngle = endAngle - startAngle\n\n\t\t// Approximate the arc using cubic bezier curves\n\t\tconst numSegments = Math.min(4, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2)))\n\t\tconst anglePerSegment = sweepAngle / numSegments\n\n\t\t// Helper function to compute point on ellipse\n\t\tconst ellipsePoint = (angle: number) => {\n\t\t\treturn {\n\t\t\t\tx: cx + rx1 * Math.cos(angle) * cosPhi - ry1 * Math.sin(angle) * sinPhi,\n\t\t\t\ty: cy + rx1 * Math.cos(angle) * sinPhi + ry1 * Math.sin(angle) * cosPhi,\n\t\t\t}\n\t\t}\n\n\t\t// Helper function to compute derivative (tangent vector) at a point on the ellipse\n\t\tconst ellipseDerivative = (angle: number) => {\n\t\t\treturn {\n\t\t\t\tx: -rx1 * Math.sin(angle) * cosPhi - ry1 * Math.cos(angle) * sinPhi,\n\t\t\t\ty: -rx1 * Math.sin(angle) * sinPhi + ry1 * Math.cos(angle) * cosPhi,\n\t\t\t}\n\t\t}\n\n\t\t// Generate cubic bezier approximations\n\t\tfor (let i = 0; i < numSegments; i++) {\n\t\t\tconst theta1 = startAngle + i * anglePerSegment\n\t\t\tconst theta2 = startAngle + (i + 1) * anglePerSegment\n\t\t\tconst deltaTheta = theta2 - theta1\n\n\t\t\tconst start = ellipsePoint(theta1)\n\t\t\tconst end = ellipsePoint(theta2)\n\n\t\t\t// Get the derivative at the start and end points\n\t\t\tconst d1 = ellipseDerivative(theta1)\n\t\t\tconst d2 = ellipseDerivative(theta2)\n\n\t\t\t// Calculate the length of the tangent handles\n\t\t\t// This is a key factor for the accuracy of the approximation\n\t\t\t// For a 90\u00B0 arc, the handle length should be 4/3 * tan(\u03C0/8) * r\n\t\t\t// For smaller arcs, we scale this value by the angle ratio\n\t\t\tconst handleScale = (4 / 3) * Math.tan(deltaTheta / 4)\n\n\t\t\t// Create control points that are tangent to the ellipse at the endpoints\n\t\t\tconst cp1x = start.x + handleScale * d1.x\n\t\t\tconst cp1y = start.y + handleScale * d1.y\n\n\t\t\tconst cp2x = end.x - handleScale * d2.x\n\t\t\tconst cp2y = end.y - handleScale * d2.y\n\n\t\t\tconst bezierOpts = i === 0 ? opts : { ...opts, mergeWithPrevious: true }\n\t\t\tthis.cubicBezierTo(end.x, end.y, cp1x, cp1y, cp2x, cp2y, bezierOpts)\n\t\t}\n\n\t\treturn this\n\t}\n\n\tcubicBezierTo(\n\t\tx: number,\n\t\ty: number,\n\t\tcp1X: number,\n\t\tcp1Y: number,\n\t\tcp2X: number,\n\t\tcp2Y: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\tthis.assertHasMoveTo()\n\t\tthis.commands.push({\n\t\t\ttype: 'cubic',\n\t\t\tx,\n\t\t\ty,\n\t\t\tcp1: { x: cp1X, y: cp1Y },\n\t\t\tcp2: { x: cp2X, y: cp2Y },\n\t\t\tisClose: false,\n\t\t\topts,\n\t\t})\n\t\treturn this\n\t}\n\n\tclose() {\n\t\tconst lastMoveTo = this.assertHasMoveTo()\n\t\tconst lastCommand = this.commands[this.commands.length - 1]\n\n\t\tif (approximately(lastMoveTo.x, lastCommand.x) && approximately(lastMoveTo.y, lastCommand.y)) {\n\t\t\tlastCommand.isClose = true\n\t\t} else {\n\t\t\tthis.commands.push({\n\t\t\t\ttype: 'line',\n\t\t\t\tx: lastMoveTo.x,\n\t\t\t\ty: lastMoveTo.y,\n\t\t\t\tisClose: true,\n\t\t\t})\n\t\t}\n\n\t\tlastMoveTo.closeIdx = this.commands.length - 1\n\t\tthis.lastMoveTo = null\n\t\treturn this\n\t}\n\n\ttoD(opts: PathBuilderToDOpts = {}) {\n\t\tconst { startIdx = 0, endIdx = this.commands.length, onlyFilled = false } = opts\n\t\tconst parts = []\n\n\t\tlet isSkippingCurrentLine = false\n\n\t\tlet didAddMove = false\n\t\tlet didAddNaturalMove = false\n\n\t\tconst addMoveIfNeeded = (i: number) => {\n\t\t\tif (didAddMove || i === 0) return\n\t\t\tdidAddMove = true\n\t\t\tconst command = this.commands[i - 1]\n\t\t\tparts.push('M', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t}\n\n\t\tfor (let i = startIdx; i < endIdx; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tswitch (command.type) {\n\t\t\t\tcase 'move': {\n\t\t\t\t\tconst isFilled =\n\t\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\t\tif (onlyFilled && !isFilled) {\n\t\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t\t} else {\n\t\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\t\tdidAddMove = true\n\t\t\t\t\t\tdidAddNaturalMove = true\n\t\t\t\t\t\tparts.push('M', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'line':\n\t\t\t\t\tif (isSkippingCurrentLine) break\n\t\t\t\t\taddMoveIfNeeded(i)\n\t\t\t\t\tif (command.isClose && didAddNaturalMove) {\n\t\t\t\t\t\tparts.push('Z')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparts.push('L', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic':\n\t\t\t\t\tif (isSkippingCurrentLine) break\n\t\t\t\t\taddMoveIfNeeded(i)\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t'C',\n\t\t\t\t\t\ttoDomPrecision(command.cp1.x),\n\t\t\t\t\t\ttoDomPrecision(command.cp1.y),\n\t\t\t\t\t\ttoDomPrecision(command.cp2.x),\n\t\t\t\t\t\ttoDomPrecision(command.cp2.y),\n\t\t\t\t\t\ttoDomPrecision(command.x),\n\t\t\t\t\t\ttoDomPrecision(command.y)\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t}\n\t\t}\n\t\treturn parts.join(' ')\n\t}\n\n\ttoSvg(opts: PathBuilderOpts) {\n\t\tif (opts.forceSolid) {\n\t\t\treturn this.toSolidSvg(opts)\n\t\t}\n\t\tswitch (opts.style) {\n\t\t\tcase 'solid':\n\t\t\t\treturn this.toSolidSvg(opts)\n\t\t\tcase 'dashed':\n\t\t\tcase 'dotted':\n\t\t\t\treturn this.toDashedSvg(opts)\n\t\t\tcase 'draw': {\n\t\t\t\tconst d = this.toDrawSvg(opts)\n\t\t\t\treturn d\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(opts, 'style')\n\t\t}\n\t}\n\n\ttoGeometry(): PathBuilderGeometry2d | Group2d {\n\t\tconst geometries = []\n\n\t\tlet current: null | {\n\t\t\tstartIdx: number\n\t\t\tmoveCommand: MoveToPathBuilderCommand\n\t\t\tisClosed: boolean\n\t\t\topts?: PathBuilderLineOpts\n\t\t} = null\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\n\t\t\tif (command.type === 'move') {\n\t\t\t\tif (current && current.opts?.geometry !== false) {\n\t\t\t\t\tgeometries.push(\n\t\t\t\t\t\tnew PathBuilderGeometry2d(this, current.startIdx, i, {\n\t\t\t\t\t\t\t...current.opts?.geometry,\n\t\t\t\t\t\t\tisFilled: current.opts?.geometry?.isFilled ?? false,\n\t\t\t\t\t\t\tisClosed: current.moveCommand.closeIdx !== null,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcurrent = { startIdx: i, moveCommand: command, opts: command.opts, isClosed: false }\n\t\t\t}\n\n\t\t\tif (command.isClose) {\n\t\t\t\tassert(current, 'No current move command')\n\t\t\t\tcurrent.isClosed = true\n\t\t\t}\n\t\t}\n\n\t\tif (current && current.opts?.geometry !== false) {\n\t\t\tgeometries.push(\n\t\t\t\tnew PathBuilderGeometry2d(this, current.startIdx, this.commands.length, {\n\t\t\t\t\t...current.opts?.geometry,\n\t\t\t\t\tisFilled: current.opts?.geometry?.isFilled ?? false,\n\t\t\t\t\tisClosed: current.moveCommand.closeIdx !== null,\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\n\t\tassert(geometries.length > 0)\n\t\tif (geometries.length === 1) return geometries[0]\n\t\treturn new Group2d({ children: geometries })\n\t}\n\n\tprivate toSolidSvg(opts: PathBuilderOpts) {\n\t\tconst { strokeWidth, props } = opts\n\n\t\treturn (\n\t\t\t<path strokeWidth={strokeWidth} d={this.toD({ onlyFilled: opts.onlyFilled })} {...props} />\n\t\t)\n\t}\n\n\tprivate toDashedSvg(opts: DashedPathBuilderOpts) {\n\t\tconst {\n\t\t\tstyle,\n\t\t\tstrokeWidth,\n\t\t\tsnap,\n\t\t\tlengthRatio,\n\t\t\tprops: { markerStart, markerEnd, ...props } = {},\n\t\t} = opts\n\n\t\tconst parts: ReactNode[] = []\n\n\t\tlet isCurrentPathClosed = false\n\t\tlet isSkippingCurrentLine = false\n\t\tlet currentLineOpts: PathBuilderLineOpts | undefined = undefined\n\n\t\tlet currentRun: {\n\t\t\tstartIdx: number\n\t\t\tendIdx: number\n\t\t\tisFirst: boolean\n\t\t\tisLast: boolean\n\t\t\tlength: number\n\t\t\tlineOpts: PathBuilderLineOpts | undefined\n\t\t\tpathIsClosed: boolean\n\t\t} | null = null\n\n\t\tconst addCurrentRun = () => {\n\t\t\tif (!currentRun) return\n\t\t\tconst { startIdx, endIdx, isFirst, isLast, length, lineOpts, pathIsClosed } = currentRun\n\t\t\tcurrentRun = null\n\n\t\t\tif (startIdx === endIdx && this.commands[startIdx].type === 'move') return\n\n\t\t\tconst start = lineOpts?.dashStart ?? opts.start\n\t\t\tconst end = lineOpts?.dashEnd ?? opts.end\n\t\t\tconst { strokeDasharray, strokeDashoffset } = getPerfectDashProps(length, strokeWidth, {\n\t\t\t\tstyle,\n\t\t\t\tsnap,\n\t\t\t\tlengthRatio,\n\t\t\t\tstart: isFirst ? (start ?? (pathIsClosed ? 'outset' : 'none')) : 'outset',\n\t\t\t\tend: isLast ? (end ?? (pathIsClosed ? 'outset' : 'none')) : 'outset',\n\t\t\t})\n\n\t\t\tconst d = this.toD({ startIdx, endIdx: endIdx + 1 })\n\t\t\tparts.push(\n\t\t\t\t<path\n\t\t\t\t\tkey={parts.length}\n\t\t\t\t\td={d}\n\t\t\t\t\tstrokeDasharray={strokeDasharray}\n\t\t\t\t\tstrokeDashoffset={strokeDashoffset}\n\t\t\t\t\tmarkerStart={isFirst ? markerStart : undefined}\n\t\t\t\t\tmarkerEnd={isLast ? markerEnd : undefined}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tconst lastCommand = this.commands[i - 1]\n\t\t\tif (command.type === 'move') {\n\t\t\t\tisCurrentPathClosed = command.closeIdx !== null\n\t\t\t\tconst isFilled =\n\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\tif (opts.onlyFilled && !isFilled) {\n\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t} else {\n\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\tcurrentLineOpts = command.opts\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (isSkippingCurrentLine) continue\n\n\t\t\tconst segmentLength = this.calculateSegmentLength(lastCommand, command)\n\t\t\tconst isFirst = lastCommand.type === 'move'\n\t\t\tconst isLast =\n\t\t\t\tcommand.isClose || i === this.commands.length - 1 || this.commands[i + 1]?.type === 'move'\n\n\t\t\tif (currentRun && command.opts?.mergeWithPrevious) {\n\t\t\t\tcurrentRun.length += segmentLength\n\t\t\t\tcurrentRun.endIdx = i\n\t\t\t\tcurrentRun.isLast = isLast\n\t\t\t} else {\n\t\t\t\taddCurrentRun()\n\t\t\t\tcurrentRun = {\n\t\t\t\t\tstartIdx: i,\n\t\t\t\t\tendIdx: i,\n\t\t\t\t\tisFirst,\n\t\t\t\t\tisLast,\n\t\t\t\t\tlength: segmentLength,\n\t\t\t\t\tlineOpts: currentLineOpts,\n\t\t\t\t\tpathIsClosed: isCurrentPathClosed,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\taddCurrentRun()\n\n\t\treturn (\n\t\t\t<g strokeWidth={strokeWidth} {...props}>\n\t\t\t\t{parts}\n\t\t\t</g>\n\t\t)\n\t}\n\n\tprivate toDrawSvg(opts: DrawPathBuilderOpts) {\n\t\treturn <path strokeWidth={opts.strokeWidth} d={this.toDrawD(opts)} {...opts.props} />\n\t}\n\n\ttoDrawD(opts: DrawPathBuilderDOpts) {\n\t\tconst {\n\t\t\tstrokeWidth,\n\t\t\trandomSeed,\n\t\t\toffset: defaultOffset = strokeWidth / 3,\n\t\t\troundness: defaultRoundness = strokeWidth * 2,\n\t\t\tpasses = 2,\n\t\t\tonlyFilled = false,\n\t\t} = opts\n\n\t\tconst parts = []\n\n\t\tconst commandInfo = this.getCommandInfo()\n\n\t\t// for each command, we draw the line for the command, plus the corner to the next command.\n\t\tconst drawCommands = []\n\t\tlet lastMoveCommandIdx = null\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tconst offset = command.opts?.offset ?? defaultOffset\n\t\t\tconst roundness = command.opts?.roundness ?? defaultRoundness\n\n\t\t\tif (command.type === 'move') {\n\t\t\t\tlastMoveCommandIdx = i\n\t\t\t}\n\n\t\t\tconst nextIdx = command.isClose\n\t\t\t\t? assertExists(lastMoveCommandIdx) + 1\n\t\t\t\t: !this.commands[i + 1] || this.commands[i + 1].type === 'move'\n\t\t\t\t\t? undefined\n\t\t\t\t\t: i + 1\n\n\t\t\tconst nextInfo =\n\t\t\t\tnextIdx !== undefined && this.commands[nextIdx] && this.commands[nextIdx]?.type !== 'move'\n\t\t\t\t\t? commandInfo[nextIdx]\n\t\t\t\t\t: undefined\n\n\t\t\tconst currentSupportsRoundness = commandsSupportingRoundness[command.type]\n\t\t\tconst nextSupportsRoundness =\n\t\t\t\tnextIdx !== undefined ? commandsSupportingRoundness[this.commands[nextIdx].type] : false\n\n\t\t\tconst currentInfo = commandInfo[i]\n\n\t\t\tconst tangentToPrev = currentInfo?.tangentEnd\n\t\t\tconst tangentToNext = nextInfo?.tangentStart\n\n\t\t\tconst roundnessClampedForAngle =\n\t\t\t\tcurrentSupportsRoundness &&\n\t\t\t\tnextSupportsRoundness &&\n\t\t\t\ttangentToPrev &&\n\t\t\t\ttangentToNext &&\n\t\t\t\tVec.Len2(tangentToPrev) > 0.01 &&\n\t\t\t\tVec.Len2(tangentToNext) > 0.01\n\t\t\t\t\t? modulate(\n\t\t\t\t\t\t\tMath.abs(Vec.AngleBetween(tangentToPrev, tangentToNext)),\n\t\t\t\t\t\t\t[Math.PI / 2, Math.PI],\n\t\t\t\t\t\t\t[roundness, 0],\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t)\n\t\t\t\t\t: 0\n\n\t\t\tconst shortestDistance = Math.min(\n\t\t\t\tcurrentInfo?.length ?? Infinity,\n\t\t\t\tnextInfo?.length ?? Infinity\n\t\t\t)\n\t\t\tconst offsetLimit = shortestDistance - roundnessClampedForAngle * 2\n\n\t\t\tconst offsetAmount = clamp(offset, 0, offsetLimit / 4)\n\n\t\t\tconst roundnessBeforeClampedForLength = Math.min(\n\t\t\t\troundnessClampedForAngle,\n\t\t\t\t(currentInfo?.length ?? Infinity) / 4\n\t\t\t)\n\t\t\tconst roundnessAfterClampedForLength = Math.min(\n\t\t\t\troundnessClampedForAngle,\n\t\t\t\t(nextInfo?.length ?? Infinity) / 4\n\t\t\t)\n\n\t\t\tconst drawCommand = {\n\t\t\t\tcommand,\n\t\t\t\toffsetAmount,\n\t\t\t\troundnessBefore: roundnessBeforeClampedForLength,\n\t\t\t\troundnessAfter: roundnessAfterClampedForLength,\n\t\t\t\ttangentToPrev: commandInfo[i]?.tangentEnd,\n\t\t\t\ttangentToNext: nextInfo?.tangentStart,\n\t\t\t\tmoveDidClose: false,\n\t\t\t}\n\n\t\t\tdrawCommands.push(drawCommand)\n\n\t\t\tif (command.isClose && lastMoveCommandIdx !== null) {\n\t\t\t\tconst lastMoveCommand = drawCommands[lastMoveCommandIdx]\n\t\t\t\tlastMoveCommand.moveDidClose = true\n\t\t\t\tlastMoveCommand.roundnessAfter = roundnessAfterClampedForLength\n\t\t\t} else if (command.type === 'move') {\n\t\t\t\tlastMoveCommandIdx = i\n\t\t\t}\n\t\t}\n\n\t\tfor (let pass = 0; pass < passes; pass++) {\n\t\t\tconst random = rng(randomSeed + pass)\n\n\t\t\tlet lastMoveToOffset = { x: 0, y: 0 }\n\t\t\tlet isSkippingCurrentLine = false\n\t\t\tfor (const {\n\t\t\t\tcommand,\n\t\t\t\toffsetAmount,\n\t\t\t\troundnessBefore,\n\t\t\t\troundnessAfter,\n\t\t\t\ttangentToNext,\n\t\t\t\ttangentToPrev,\n\t\t\t} of drawCommands) {\n\t\t\t\tconst offset = command.isClose\n\t\t\t\t\t? lastMoveToOffset\n\t\t\t\t\t: { x: random() * offsetAmount, y: random() * offsetAmount }\n\n\t\t\t\tif (command.type === 'move') {\n\t\t\t\t\tlastMoveToOffset = offset\n\t\t\t\t\tconst isFilled =\n\t\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\t\tif (onlyFilled && !isFilled) {\n\t\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t\t} else {\n\t\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isSkippingCurrentLine) continue\n\n\t\t\t\tconst offsetPoint = Vec.Add(command, offset)\n\n\t\t\t\tconst endPoint =\n\t\t\t\t\ttangentToNext && roundnessAfter > 0\n\t\t\t\t\t\t? Vec.Mul(tangentToNext, -roundnessAfter).add(offsetPoint)\n\t\t\t\t\t\t: offsetPoint\n\n\t\t\t\tconst startPoint =\n\t\t\t\t\ttangentToPrev && roundnessBefore > 0\n\t\t\t\t\t\t? Vec.Mul(tangentToPrev, roundnessBefore).add(offsetPoint)\n\t\t\t\t\t\t: offsetPoint\n\n\t\t\t\tif (endPoint === offsetPoint || startPoint === offsetPoint) {\n\t\t\t\t\tswitch (command.type) {\n\t\t\t\t\t\tcase 'move':\n\t\t\t\t\t\t\tparts.push('M', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'line':\n\t\t\t\t\t\t\tparts.push('L', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'cubic': {\n\t\t\t\t\t\t\tconst offsetCp1 = Vec.Add(command.cp1, offset)\n\t\t\t\t\t\t\tconst offsetCp2 = Vec.Add(command.cp2, offset)\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'C',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch (command.type) {\n\t\t\t\t\t\tcase 'move':\n\t\t\t\t\t\t\tparts.push('M', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'line':\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'L',\n\t\t\t\t\t\t\t\ttoDomPrecision(startPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(startPoint.y),\n\n\t\t\t\t\t\t\t\t'Q',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'cubic': {\n\t\t\t\t\t\t\tconst offsetCp1 = Vec.Add(command.cp1, offset)\n\t\t\t\t\t\t\tconst offsetCp2 = Vec.Add(command.cp2, offset)\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'C',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn parts.join(' ')\n\t}\n\n\tprivate calculateSegmentLength(lastPoint: VecLike, command: PathBuilderCommand) {\n\t\tswitch (command.type) {\n\t\t\tcase 'move':\n\t\t\t\treturn 0\n\t\t\tcase 'line':\n\t\t\t\treturn Vec.Dist(lastPoint, command)\n\t\t\tcase 'cubic':\n\t\t\t\treturn CubicBezier.length(\n\t\t\t\t\tlastPoint.x,\n\t\t\t\t\tlastPoint.y,\n\t\t\t\t\tcommand.cp1.x,\n\t\t\t\t\tcommand.cp1.y,\n\t\t\t\t\tcommand.cp2.x,\n\t\t\t\t\tcommand.cp2.y,\n\t\t\t\t\tcommand.x,\n\t\t\t\t\tcommand.y\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t}\n\t}\n\n\t/** @internal */\n\tgetCommands(): readonly PathBuilderCommand[] {\n\t\treturn this.commands\n\t}\n\n\t/** @internal */\n\tgetCommandInfo() {\n\t\tconst commandInfo: Array<undefined | PathBuilderCommandInfo> = []\n\t\tfor (let i = 1; i < this.commands.length; i++) {\n\t\t\tconst previous = this.commands[i - 1]\n\t\t\tconst current = this.commands[i]\n\n\t\t\tif (current._info) {\n\t\t\t\tcommandInfo[i] = current._info\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (current.type === 'move') {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlet tangentStart, tangentEnd\n\t\t\tswitch (current.type) {\n\t\t\t\tcase 'line':\n\t\t\t\t\ttangentStart = tangentEnd = Vec.Sub(previous, current).uni()\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic': {\n\t\t\t\t\ttangentStart = Vec.Sub(current.cp1, previous).uni()\n\t\t\t\t\ttangentEnd = Vec.Sub(current.cp2, current).uni()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(current, 'type')\n\t\t\t}\n\n\t\t\tcurrent._info = {\n\t\t\t\ttangentStart,\n\t\t\t\ttangentEnd,\n\t\t\t\tlength: this.calculateSegmentLength(previous, current),\n\t\t\t}\n\t\t\tcommandInfo[i] = current._info\n\t\t}\n\n\t\treturn commandInfo\n\t}\n}\n\nconst commandsSupportingRoundness = {\n\tline: true,\n\tmove: true,\n\tcubic: false,\n} as const satisfies Record<PathBuilderCommand['type'], boolean>\n\n/** @public */\nexport class PathBuilderGeometry2d extends Geometry2d {\n\tconstructor(\n\t\tprivate readonly path: PathBuilder,\n\t\tprivate readonly startIdx: number,\n\t\tprivate readonly endIdx: number,\n\t\toptions: Geometry2dOptions\n\t) {\n\t\tsuper(options)\n\t}\n\n\tprivate _segments: Geometry2d[] | null = null\n\tgetSegments() {\n\t\tif (this._segments) return this._segments\n\n\t\tthis._segments = []\n\t\tlet last = this.path.commands[this.startIdx]\n\t\tassert(last.type === 'move')\n\n\t\tfor (let i = this.startIdx + 1; i < this.endIdx; i++) {\n\t\t\tconst command = this.path.commands[i]\n\t\t\tassert(command.type !== 'move')\n\n\t\t\tswitch (command.type) {\n\t\t\t\tcase 'line':\n\t\t\t\t\tthis._segments.push(new Edge2d({ start: Vec.From(last), end: Vec.From(command) }))\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic': {\n\t\t\t\t\tthis._segments.push(\n\t\t\t\t\t\tnew CubicBezier2d({\n\t\t\t\t\t\t\tstart: Vec.From(last),\n\t\t\t\t\t\t\tcp1: Vec.From(command.cp1),\n\t\t\t\t\t\t\tcp2: Vec.From(command.cp2),\n\t\t\t\t\t\t\tend: Vec.From(command),\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t}\n\n\t\t\tlast = command\n\t\t}\n\n\t\treturn this._segments\n\t}\n\n\toverride getVertices(filters: Geometry2dFilters): Vec[] {\n\t\tconst vs = this.getSegments()\n\t\t\t.flatMap((s) => s.getVertices(filters))\n\t\t\t.filter((vertex, i, vertices) => {\n\t\t\t\tconst prev = vertices[i - 1]\n\t\t\t\tif (!prev) return true\n\t\t\t\treturn !Vec.Equals(prev, vertex)\n\t\t\t})\n\n\t\tif (this.isClosed) {\n\t\t\tconst last = vs[vs.length - 1]\n\t\t\tconst first = vs[0]\n\t\t\tif (!Vec.Equals(last, first)) {\n\t\t\t\tvs.push(first)\n\t\t\t}\n\t\t}\n\n\t\treturn vs\n\t}\n\n\toverride nearestPoint(point: VecLike, _filters?: Geometry2dFilters): Vec {\n\t\tlet nearest: Vec | null = null\n\t\tlet nearestDistance = Infinity\n\n\t\tfor (const segment of this.getSegments()) {\n\t\t\tconst candidate = segment.nearestPoint(point)\n\t\t\tconst distance = Vec.Dist2(point, candidate)\n\t\t\tif (distance < nearestDistance) {\n\t\t\t\tnearestDistance = distance\n\t\t\t\tnearest = candidate\n\t\t\t}\n\t\t}\n\n\t\tassert(nearest, 'No nearest point found')\n\t\treturn nearest\n\t}\n\n\toverride hitTestLineSegment(\n\t\tA: VecLike,\n\t\tB: VecLike,\n\t\tdistance = 0,\n\t\tfilters?: Geometry2dFilters\n\t): boolean {\n\t\treturn super.hitTestLineSegment(A, B, distance, filters)\n\t}\n\toverride getSvgPathData(): string {\n\t\treturn this.path.toD({ startIdx: this.startIdx, endIdx: this.endIdx })\n\t}\n}\n\n/*!\n * Adapted from https://github.com/adobe-webplatform/Snap.svg/tree/master\n * Apache License: https://github.com/adobe-webplatform/Snap.svg/blob/master/LICENSE\n * https://github.com/adobe-webplatform/Snap.svg/blob/c8e483c9694517e24b282f8f59f985629f4994ce/dist/snap.svg.js#L5786\n */\nconst CubicBezier = {\n\tbase3(t: number, p1: number, p2: number, p3: number, p4: number) {\n\t\tconst t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4\n\t\tconst t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3\n\t\treturn t * t2 - 3 * p1 + 3 * p2\n\t},\n\t/**\n\t * Calculate the approximate length of a cubic bezier curve from (x1, y1) to (x4, y4) with\n\t * control points (x2, y2) and (x3, y3).\n\t */\n\tlength(\n\t\tx1: number,\n\t\ty1: number,\n\t\tx2: number,\n\t\ty2: number,\n\t\tx3: number,\n\t\ty3: number,\n\t\tx4: number,\n\t\ty4: number,\n\t\tz = 1\n\t) {\n\t\tz = z > 1 ? 1 : z < 0 ? 0 : z\n\t\tconst z2 = z / 2\n\t\tconst n = 12\n\n\t\tlet sum = 0\n\t\tsum = 0\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tconst ct = z2 * CubicBezier.Tvalues[i] + z2\n\t\t\tconst xbase = CubicBezier.base3(ct, x1, x2, x3, x4)\n\t\t\tconst ybase = CubicBezier.base3(ct, y1, y2, y3, y4)\n\t\t\tconst comb = xbase * xbase + ybase * ybase\n\t\t\tsum += CubicBezier.Cvalues[i] * Math.sqrt(comb)\n\t\t}\n\t\treturn z2 * sum\n\t},\n\tTvalues: [\n\t\t-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816,\n\t\t0.9816,\n\t],\n\tCvalues: [\n\t\t0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472,\n\t],\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tapproximately,\n\tassert,\n\tassertExists,\n\tclamp,\n\tCubicBezier2d,\n\tEdge2d,\n\texhaustiveSwitchError,\n\tGeometry2d,\n\tGeometry2dFilters,\n\tGeometry2dOptions,\n\tgetPerfectDashProps,\n\tgetVerticesCountForArcLength,\n\tGroup2d,\n\tmodulate,\n\tPerfectDashTerminal,\n\trng,\n\ttoDomPrecision,\n\tVec,\n\tVecLike,\n\tVecModel,\n} from '@tldraw/editor'\nimport { ReactNode, SVGProps } from 'react'\n\n/** @public */\nexport interface BasePathBuilderOpts {\n\tstrokeWidth: number\n\tforceSolid?: boolean\n\tonlyFilled?: boolean\n\tprops?: SVGProps<SVGPathElement & SVGGElement>\n}\n\n/** @public */\nexport interface SolidPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'solid'\n}\n\n/** @public */\nexport interface DashedPathBuilderOpts extends BasePathBuilderOpts {\n\tstyle: 'dashed' | 'dotted'\n\tsnap?: number\n\tend?: PerfectDashTerminal\n\tstart?: PerfectDashTerminal\n\tlengthRatio?: number\n}\n\n/** @public */\nexport interface DrawPathBuilderDOpts {\n\tstrokeWidth: number\n\trandomSeed: string\n\toffset?: number\n\troundness?: number\n\tpasses?: number\n\tonlyFilled?: boolean\n}\n\n/** @public */\nexport interface DrawPathBuilderOpts extends BasePathBuilderOpts, DrawPathBuilderDOpts {\n\tstyle: 'draw'\n}\n\n/** @public */\nexport type PathBuilderOpts = SolidPathBuilderOpts | DashedPathBuilderOpts | DrawPathBuilderOpts\n\n/** @public */\nexport interface PathBuilderCommandOpts {\n\t/**\n\t * When converting to a draw-style line, how much offset from the original point should be\n\t * applied?\n\t */\n\toffset?: number\n\t/**\n\t * When converting to a draw-style line, how much roundness should be applied to the end of this\n\t * line?\n\t */\n\troundness?: number\n\t/**\n\t * When converting to a dash- or dot-style line, should the current segment be merged with the\n\t * previous segment when calculating the dash pattern? This is false by default, meaning each\n\t * command will start/end on a dash/dot boundary.\n\t */\n\tmergeWithPrevious?: boolean\n}\n\n/** @internal */\nexport interface PathBuilderCommandInfo {\n\ttangentStart: VecModel\n\ttangentEnd: VecModel\n\tlength: number\n}\n\n/** @internal */\nexport interface PathBuilderCommandBase {\n\topts?: PathBuilderCommandOpts\n\tx: number\n\ty: number\n\tisClose: boolean\n\t_info?: PathBuilderCommandInfo\n}\n\n/** @public */\nexport interface PathBuilderLineOpts extends PathBuilderCommandOpts {\n\tgeometry?: Omit<Geometry2dOptions, 'isClosed'> | false\n\tdashStart?: PerfectDashTerminal\n\tdashEnd?: PerfectDashTerminal\n}\n\n/** @internal */\nexport interface MoveToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'move'\n\tcloseIdx: number | null\n\topts?: PathBuilderLineOpts\n}\n\n/** @internal */\nexport interface LineToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'line'\n}\n\n/** @internal */\nexport interface CubicBezierToPathBuilderCommand extends PathBuilderCommandBase {\n\ttype: 'cubic'\n\tcp1: VecModel\n\tcp2: VecModel\n\tresolution?: number\n}\n\n/** @internal */\nexport type PathBuilderCommand =\n\t| MoveToPathBuilderCommand\n\t| LineToPathBuilderCommand\n\t| CubicBezierToPathBuilderCommand\n\n/** @public */\nexport interface PathBuilderToDOpts {\n\tstartIdx?: number\n\tendIdx?: number\n\tonlyFilled?: boolean\n}\n\n/** @public */\nexport class PathBuilder {\n\tstatic lineThroughPoints(\n\t\tpoints: VecLike[],\n\t\topts?: PathBuilderLineOpts & { endOffsets?: number }\n\t) {\n\t\tconst path = new PathBuilder()\n\t\tpath.moveTo(points[0].x, points[0].y, { ...opts, offset: opts?.endOffsets ?? opts?.offset })\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst isLast = i === points.length - 1\n\t\t\tpath.lineTo(points[i].x, points[i].y, isLast ? { offset: opts?.endOffsets } : undefined)\n\t\t}\n\t\treturn path\n\t}\n\n\tstatic cubicSplineThroughPoints(\n\t\tpoints: VecLike[],\n\t\topts?: PathBuilderLineOpts & { endOffsets?: number }\n\t) {\n\t\tconst path = new PathBuilder()\n\t\tconst len = points.length\n\t\tconst last = len - 2\n\t\tconst k = 1.25\n\n\t\tpath.moveTo(points[0].x, points[0].y, { ...opts, offset: opts?.endOffsets ?? opts?.offset })\n\n\t\tfor (let i = 0; i < len - 1; i++) {\n\t\t\tconst p0 = i === 0 ? points[0] : points[i - 1]\n\t\t\tconst p1 = points[i]\n\t\t\tconst p2 = points[i + 1]\n\t\t\tconst p3 = i === last ? p2 : points[i + 2]\n\n\t\t\tlet cp1x, cp1y, cp2x, cp2y\n\t\t\tif (i === 0) {\n\t\t\t\tcp1x = p0.x\n\t\t\t\tcp1y = p0.y\n\t\t\t} else {\n\t\t\t\tcp1x = p1.x + ((p2.x - p0.x) / 6) * k\n\t\t\t\tcp1y = p1.y + ((p2.y - p0.y) / 6) * k\n\t\t\t}\n\n\t\t\tlet pointOpts = undefined\n\t\t\tif (i === last) {\n\t\t\t\tcp2x = p2.x\n\t\t\t\tcp2y = p2.y\n\t\t\t\tpointOpts = { offset: opts?.endOffsets }\n\t\t\t} else {\n\t\t\t\tcp2x = p2.x - ((p3.x - p1.x) / 6) * k\n\t\t\t\tcp2y = p2.y - ((p3.y - p1.y) / 6) * k\n\t\t\t}\n\n\t\t\tpath.cubicBezierTo(p2.x, p2.y, cp1x, cp1y, cp2x, cp2y, pointOpts)\n\t\t}\n\n\t\treturn path\n\t}\n\n\tconstructor() {}\n\n\t/** @internal */\n\tcommands: PathBuilderCommand[] = []\n\n\tprivate lastMoveTo: MoveToPathBuilderCommand | null = null\n\tprivate assertHasMoveTo() {\n\t\tassert(this.lastMoveTo, 'Start an SVGPathBuilder with `.moveTo()`')\n\t\treturn this.lastMoveTo\n\t}\n\n\tmoveTo(x: number, y: number, opts?: PathBuilderLineOpts) {\n\t\tthis.lastMoveTo = { type: 'move', x, y, closeIdx: null, isClose: false, opts }\n\t\tthis.commands.push(this.lastMoveTo)\n\t\treturn this\n\t}\n\n\tlineTo(x: number, y: number, opts?: PathBuilderCommandOpts) {\n\t\tthis.assertHasMoveTo()\n\t\tthis.commands.push({ type: 'line', x, y, isClose: false, opts })\n\t\treturn this\n\t}\n\n\tcircularArcTo(\n\t\tradius: number,\n\t\tlargeArcFlag: boolean,\n\t\tsweepFlag: boolean,\n\t\tx2: number,\n\t\ty2: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\treturn this.arcTo(radius, radius, largeArcFlag, sweepFlag, 0, x2, y2, opts)\n\t}\n\n\tarcTo(\n\t\trx: number,\n\t\try: number,\n\t\tlargeArcFlag: boolean,\n\t\tsweepFlag: boolean,\n\t\txAxisRotationRadians: number,\n\t\tx2: number,\n\t\ty2: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\t// As arc flags make them very sensitive to offsets when we render them in draw mode, we\n\t\t// approximate arcs by converting them to up to 4 (1 per 90\u00B0 segment) cubic bezier curves.\n\t\t// This algorithm is a Claude special:\n\t\t// https://claude.ai/public/artifacts/5ea0bf18-4afb-4b3d-948d-31b8a77ef1e2\n\n\t\tthis.assertHasMoveTo()\n\n\t\tconst x1 = this.commands[this.commands.length - 1].x\n\t\tconst y1 = this.commands[this.commands.length - 1].y\n\n\t\t// If the endpoints are identical, don't add a command\n\t\tif (x1 === x2 && y1 === y2) {\n\t\t\treturn this\n\t\t}\n\n\t\t// If rx or ry is 0, return a straight line\n\t\tif (rx === 0 || ry === 0) {\n\t\t\treturn this.lineTo(x2, y2, opts)\n\t\t}\n\n\t\t// Convert angle from degrees to radians\n\t\tconst phi = xAxisRotationRadians\n\t\tconst sinPhi = Math.sin(phi)\n\t\tconst cosPhi = Math.cos(phi)\n\n\t\t// Ensure rx and ry are positive\n\t\tlet rx1 = Math.abs(rx)\n\t\tlet ry1 = Math.abs(ry)\n\n\t\t// Step 1: Compute (x1', y1') - transform from ellipse coordinate system to unit circle\n\t\tconst dx = (x1 - x2) / 2\n\t\tconst dy = (y1 - y2) / 2\n\t\tconst x1p = cosPhi * dx + sinPhi * dy\n\t\tconst y1p = -sinPhi * dx + cosPhi * dy\n\n\t\t// Correction of out-of-range radii\n\t\tconst lambda = (x1p * x1p) / (rx1 * rx1) + (y1p * y1p) / (ry1 * ry1)\n\t\tif (lambda > 1) {\n\t\t\tconst sqrtLambda = Math.sqrt(lambda)\n\t\t\trx1 *= sqrtLambda\n\t\t\try1 *= sqrtLambda\n\t\t}\n\n\t\t// Step 2: Compute (cx', cy') - center of ellipse in transformed system\n\t\tconst sign = largeArcFlag !== sweepFlag ? 1 : -1\n\n\t\tconst term = rx1 * rx1 * ry1 * ry1 - rx1 * rx1 * y1p * y1p - ry1 * ry1 * x1p * x1p\n\t\tconst numerator = rx1 * rx1 * y1p * y1p + ry1 * ry1 * x1p * x1p\n\n\t\tlet radicand = term / numerator\n\t\tradicand = radicand < 0 ? 0 : radicand\n\n\t\tconst coef = sign * Math.sqrt(radicand)\n\n\t\tconst cxp = coef * ((rx1 * y1p) / ry1)\n\t\tconst cyp = coef * (-(ry1 * x1p) / rx1)\n\n\t\t// Step 3: Compute (cx, cy) from (cx', cy') - transform back to original coordinate system\n\t\tconst cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2\n\t\tconst cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2\n\n\t\t// Step 4: Compute the start and end angles\n\t\tconst ux = (x1p - cxp) / rx1\n\t\tconst uy = (y1p - cyp) / ry1\n\t\tconst vx = (-x1p - cxp) / rx1\n\t\tconst vy = (-y1p - cyp) / ry1\n\n\t\tconst startAngle = Math.atan2(uy, ux)\n\t\tlet endAngle = Math.atan2(vy, vx)\n\n\t\t// Ensure correct sweep direction\n\t\tif (!sweepFlag && endAngle > startAngle) {\n\t\t\tendAngle -= 2 * Math.PI\n\t\t} else if (sweepFlag && endAngle < startAngle) {\n\t\t\tendAngle += 2 * Math.PI\n\t\t}\n\n\t\t// Calculate the sweep angle\n\t\tconst sweepAngle = endAngle - startAngle\n\n\t\t// Calculate the approximate arc length. General ellipse arc length is expensive - there's\n\t\t// no closed form solution, so we have to do iterative numerical approximation. As we only\n\t\t// use this to control the resolution of later approximations, let's cheat and just use the\n\t\t// circular arc length with the largest radius:\n\t\tconst approximateArcLength = Math.max(rx1, ry1) * Math.abs(sweepAngle)\n\n\t\t// Approximate the arc using cubic bezier curves\n\t\tconst numSegments = Math.min(4, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2)))\n\t\tconst resolutionPerSegment = Math.ceil(\n\t\t\tgetVerticesCountForArcLength(approximateArcLength) / numSegments\n\t\t)\n\t\tconst anglePerSegment = sweepAngle / numSegments\n\n\t\t// Helper function to compute point on ellipse\n\t\tconst ellipsePoint = (angle: number) => {\n\t\t\treturn {\n\t\t\t\tx: cx + rx1 * Math.cos(angle) * cosPhi - ry1 * Math.sin(angle) * sinPhi,\n\t\t\t\ty: cy + rx1 * Math.cos(angle) * sinPhi + ry1 * Math.sin(angle) * cosPhi,\n\t\t\t}\n\t\t}\n\n\t\t// Helper function to compute derivative (tangent vector) at a point on the ellipse\n\t\tconst ellipseDerivative = (angle: number) => {\n\t\t\treturn {\n\t\t\t\tx: -rx1 * Math.sin(angle) * cosPhi - ry1 * Math.cos(angle) * sinPhi,\n\t\t\t\ty: -rx1 * Math.sin(angle) * sinPhi + ry1 * Math.cos(angle) * cosPhi,\n\t\t\t}\n\t\t}\n\n\t\t// Generate cubic bezier approximations\n\t\tfor (let i = 0; i < numSegments; i++) {\n\t\t\tconst theta1 = startAngle + i * anglePerSegment\n\t\t\tconst theta2 = startAngle + (i + 1) * anglePerSegment\n\t\t\tconst deltaTheta = theta2 - theta1\n\n\t\t\tconst start = ellipsePoint(theta1)\n\t\t\tconst end = ellipsePoint(theta2)\n\n\t\t\t// Get the derivative at the start and end points\n\t\t\tconst d1 = ellipseDerivative(theta1)\n\t\t\tconst d2 = ellipseDerivative(theta2)\n\n\t\t\t// Calculate the length of the tangent handles\n\t\t\t// This is a key factor for the accuracy of the approximation\n\t\t\t// For a 90\u00B0 arc, the handle length should be 4/3 * tan(\u03C0/8) * r\n\t\t\t// For smaller arcs, we scale this value by the angle ratio\n\t\t\tconst handleScale = (4 / 3) * Math.tan(deltaTheta / 4)\n\n\t\t\t// Create control points that are tangent to the ellipse at the endpoints\n\t\t\tconst cp1x = start.x + handleScale * d1.x\n\t\t\tconst cp1y = start.y + handleScale * d1.y\n\n\t\t\tconst cp2x = end.x - handleScale * d2.x\n\t\t\tconst cp2y = end.y - handleScale * d2.y\n\n\t\t\tconst bezierOpts = i === 0 ? opts : { ...opts, mergeWithPrevious: true }\n\t\t\tthis.cubicBezierToWithResolution(\n\t\t\t\tend.x,\n\t\t\t\tend.y,\n\t\t\t\tcp1x,\n\t\t\t\tcp1y,\n\t\t\t\tcp2x,\n\t\t\t\tcp2y,\n\t\t\t\tbezierOpts,\n\t\t\t\tresolutionPerSegment\n\t\t\t)\n\t\t}\n\n\t\treturn this\n\t}\n\n\tcubicBezierTo(\n\t\tx: number,\n\t\ty: number,\n\t\tcp1X: number,\n\t\tcp1Y: number,\n\t\tcp2X: number,\n\t\tcp2Y: number,\n\t\topts?: PathBuilderCommandOpts\n\t) {\n\t\treturn this.cubicBezierToWithResolution(x, y, cp1X, cp1Y, cp2X, cp2Y, opts)\n\t}\n\tprivate cubicBezierToWithResolution(\n\t\tx: number,\n\t\ty: number,\n\t\tcp1X: number,\n\t\tcp1Y: number,\n\t\tcp2X: number,\n\t\tcp2Y: number,\n\t\topts?: PathBuilderCommandOpts,\n\t\tresolution?: number\n\t) {\n\t\tthis.assertHasMoveTo()\n\t\tthis.commands.push({\n\t\t\ttype: 'cubic',\n\t\t\tx,\n\t\t\ty,\n\t\t\tcp1: { x: cp1X, y: cp1Y },\n\t\t\tcp2: { x: cp2X, y: cp2Y },\n\t\t\tisClose: false,\n\t\t\topts,\n\t\t\tresolution,\n\t\t})\n\t\treturn this\n\t}\n\n\tclose() {\n\t\tconst lastMoveTo = this.assertHasMoveTo()\n\t\tconst lastCommand = this.commands[this.commands.length - 1]\n\n\t\tif (approximately(lastMoveTo.x, lastCommand.x) && approximately(lastMoveTo.y, lastCommand.y)) {\n\t\t\tlastCommand.isClose = true\n\t\t} else {\n\t\t\tthis.commands.push({\n\t\t\t\ttype: 'line',\n\t\t\t\tx: lastMoveTo.x,\n\t\t\t\ty: lastMoveTo.y,\n\t\t\t\tisClose: true,\n\t\t\t})\n\t\t}\n\n\t\tlastMoveTo.closeIdx = this.commands.length - 1\n\t\tthis.lastMoveTo = null\n\t\treturn this\n\t}\n\n\ttoD(opts: PathBuilderToDOpts = {}) {\n\t\tconst { startIdx = 0, endIdx = this.commands.length, onlyFilled = false } = opts\n\t\tconst parts = []\n\n\t\tlet isSkippingCurrentLine = false\n\n\t\tlet didAddMove = false\n\t\tlet didAddNaturalMove = false\n\n\t\tconst addMoveIfNeeded = (i: number) => {\n\t\t\tif (didAddMove || i === 0) return\n\t\t\tdidAddMove = true\n\t\t\tconst command = this.commands[i - 1]\n\t\t\tparts.push('M', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t}\n\n\t\tfor (let i = startIdx; i < endIdx; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tswitch (command.type) {\n\t\t\t\tcase 'move': {\n\t\t\t\t\tconst isFilled =\n\t\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\t\tif (onlyFilled && !isFilled) {\n\t\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t\t} else {\n\t\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\t\tdidAddMove = true\n\t\t\t\t\t\tdidAddNaturalMove = true\n\t\t\t\t\t\tparts.push('M', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'line':\n\t\t\t\t\tif (isSkippingCurrentLine) break\n\t\t\t\t\taddMoveIfNeeded(i)\n\t\t\t\t\tif (command.isClose && didAddNaturalMove) {\n\t\t\t\t\t\tparts.push('Z')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparts.push('L', toDomPrecision(command.x), toDomPrecision(command.y))\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic':\n\t\t\t\t\tif (isSkippingCurrentLine) break\n\t\t\t\t\taddMoveIfNeeded(i)\n\t\t\t\t\tparts.push(\n\t\t\t\t\t\t'C',\n\t\t\t\t\t\ttoDomPrecision(command.cp1.x),\n\t\t\t\t\t\ttoDomPrecision(command.cp1.y),\n\t\t\t\t\t\ttoDomPrecision(command.cp2.x),\n\t\t\t\t\t\ttoDomPrecision(command.cp2.y),\n\t\t\t\t\t\ttoDomPrecision(command.x),\n\t\t\t\t\t\ttoDomPrecision(command.y)\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t}\n\t\t}\n\t\treturn parts.join(' ')\n\t}\n\n\ttoSvg(opts: PathBuilderOpts) {\n\t\tif (opts.forceSolid) {\n\t\t\treturn this.toSolidSvg(opts)\n\t\t}\n\t\tswitch (opts.style) {\n\t\t\tcase 'solid':\n\t\t\t\treturn this.toSolidSvg(opts)\n\t\t\tcase 'dashed':\n\t\t\tcase 'dotted':\n\t\t\t\treturn this.toDashedSvg(opts)\n\t\t\tcase 'draw': {\n\t\t\t\tconst d = this.toDrawSvg(opts)\n\t\t\t\treturn d\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(opts, 'style')\n\t\t}\n\t}\n\n\ttoGeometry(): PathBuilderGeometry2d | Group2d {\n\t\tconst geometries = []\n\n\t\tlet current: null | {\n\t\t\tstartIdx: number\n\t\t\tmoveCommand: MoveToPathBuilderCommand\n\t\t\tisClosed: boolean\n\t\t\topts?: PathBuilderLineOpts\n\t\t} = null\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\n\t\t\tif (command.type === 'move') {\n\t\t\t\tif (current && current.opts?.geometry !== false) {\n\t\t\t\t\tgeometries.push(\n\t\t\t\t\t\tnew PathBuilderGeometry2d(this, current.startIdx, i, {\n\t\t\t\t\t\t\t...current.opts?.geometry,\n\t\t\t\t\t\t\tisFilled: current.opts?.geometry?.isFilled ?? false,\n\t\t\t\t\t\t\tisClosed: current.moveCommand.closeIdx !== null,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcurrent = { startIdx: i, moveCommand: command, opts: command.opts, isClosed: false }\n\t\t\t}\n\n\t\t\tif (command.isClose) {\n\t\t\t\tassert(current, 'No current move command')\n\t\t\t\tcurrent.isClosed = true\n\t\t\t}\n\t\t}\n\n\t\tif (current && current.opts?.geometry !== false) {\n\t\t\tgeometries.push(\n\t\t\t\tnew PathBuilderGeometry2d(this, current.startIdx, this.commands.length, {\n\t\t\t\t\t...current.opts?.geometry,\n\t\t\t\t\tisFilled: current.opts?.geometry?.isFilled ?? false,\n\t\t\t\t\tisClosed: current.moveCommand.closeIdx !== null,\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\n\t\tassert(geometries.length > 0)\n\t\tif (geometries.length === 1) return geometries[0]\n\t\treturn new Group2d({ children: geometries })\n\t}\n\n\tprivate toSolidSvg(opts: PathBuilderOpts) {\n\t\tconst { strokeWidth, props } = opts\n\n\t\treturn (\n\t\t\t<path strokeWidth={strokeWidth} d={this.toD({ onlyFilled: opts.onlyFilled })} {...props} />\n\t\t)\n\t}\n\n\tprivate toDashedSvg(opts: DashedPathBuilderOpts) {\n\t\tconst {\n\t\t\tstyle,\n\t\t\tstrokeWidth,\n\t\t\tsnap,\n\t\t\tlengthRatio,\n\t\t\tprops: { markerStart, markerEnd, ...props } = {},\n\t\t} = opts\n\n\t\tconst parts: ReactNode[] = []\n\n\t\tlet isCurrentPathClosed = false\n\t\tlet isSkippingCurrentLine = false\n\t\tlet currentLineOpts: PathBuilderLineOpts | undefined = undefined\n\n\t\tlet currentRun: {\n\t\t\tstartIdx: number\n\t\t\tendIdx: number\n\t\t\tisFirst: boolean\n\t\t\tisLast: boolean\n\t\t\tlength: number\n\t\t\tlineOpts: PathBuilderLineOpts | undefined\n\t\t\tpathIsClosed: boolean\n\t\t} | null = null\n\n\t\tconst addCurrentRun = () => {\n\t\t\tif (!currentRun) return\n\t\t\tconst { startIdx, endIdx, isFirst, isLast, length, lineOpts, pathIsClosed } = currentRun\n\t\t\tcurrentRun = null\n\n\t\t\tif (startIdx === endIdx && this.commands[startIdx].type === 'move') return\n\n\t\t\tconst start = lineOpts?.dashStart ?? opts.start\n\t\t\tconst end = lineOpts?.dashEnd ?? opts.end\n\t\t\tconst { strokeDasharray, strokeDashoffset } = getPerfectDashProps(length, strokeWidth, {\n\t\t\t\tstyle,\n\t\t\t\tsnap,\n\t\t\t\tlengthRatio,\n\t\t\t\tstart: isFirst ? (start ?? (pathIsClosed ? 'outset' : 'none')) : 'outset',\n\t\t\t\tend: isLast ? (end ?? (pathIsClosed ? 'outset' : 'none')) : 'outset',\n\t\t\t})\n\n\t\t\tconst d = this.toD({ startIdx, endIdx: endIdx + 1 })\n\t\t\tparts.push(\n\t\t\t\t<path\n\t\t\t\t\tkey={parts.length}\n\t\t\t\t\td={d}\n\t\t\t\t\tstrokeDasharray={strokeDasharray}\n\t\t\t\t\tstrokeDashoffset={strokeDashoffset}\n\t\t\t\t\tmarkerStart={isFirst ? markerStart : undefined}\n\t\t\t\t\tmarkerEnd={isLast ? markerEnd : undefined}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tconst lastCommand = this.commands[i - 1]\n\t\t\tif (command.type === 'move') {\n\t\t\t\tisCurrentPathClosed = command.closeIdx !== null\n\t\t\t\tconst isFilled =\n\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\tif (opts.onlyFilled && !isFilled) {\n\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t} else {\n\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\tcurrentLineOpts = command.opts\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (isSkippingCurrentLine) continue\n\n\t\t\tconst segmentLength = this.calculateSegmentLength(lastCommand, command)\n\t\t\tconst isFirst = lastCommand.type === 'move'\n\t\t\tconst isLast =\n\t\t\t\tcommand.isClose || i === this.commands.length - 1 || this.commands[i + 1]?.type === 'move'\n\n\t\t\tif (currentRun && command.opts?.mergeWithPrevious) {\n\t\t\t\tcurrentRun.length += segmentLength\n\t\t\t\tcurrentRun.endIdx = i\n\t\t\t\tcurrentRun.isLast = isLast\n\t\t\t} else {\n\t\t\t\taddCurrentRun()\n\t\t\t\tcurrentRun = {\n\t\t\t\t\tstartIdx: i,\n\t\t\t\t\tendIdx: i,\n\t\t\t\t\tisFirst,\n\t\t\t\t\tisLast,\n\t\t\t\t\tlength: segmentLength,\n\t\t\t\t\tlineOpts: currentLineOpts,\n\t\t\t\t\tpathIsClosed: isCurrentPathClosed,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\taddCurrentRun()\n\n\t\treturn (\n\t\t\t<g strokeWidth={strokeWidth} {...props}>\n\t\t\t\t{parts}\n\t\t\t</g>\n\t\t)\n\t}\n\n\tprivate toDrawSvg(opts: DrawPathBuilderOpts) {\n\t\treturn <path strokeWidth={opts.strokeWidth} d={this.toDrawD(opts)} {...opts.props} />\n\t}\n\n\ttoDrawD(opts: DrawPathBuilderDOpts) {\n\t\tconst {\n\t\t\tstrokeWidth,\n\t\t\trandomSeed,\n\t\t\toffset: defaultOffset = strokeWidth / 3,\n\t\t\troundness: defaultRoundness = strokeWidth * 2,\n\t\t\tpasses = 2,\n\t\t\tonlyFilled = false,\n\t\t} = opts\n\n\t\tconst parts = []\n\n\t\tconst commandInfo = this.getCommandInfo()\n\n\t\t// for each command, we draw the line for the command, plus the corner to the next command.\n\t\tconst drawCommands = []\n\t\tlet lastMoveCommandIdx = null\n\t\tfor (let i = 0; i < this.commands.length; i++) {\n\t\t\tconst command = this.commands[i]\n\t\t\tconst offset = command.opts?.offset ?? defaultOffset\n\t\t\tconst roundness = command.opts?.roundness ?? defaultRoundness\n\n\t\t\tif (command.type === 'move') {\n\t\t\t\tlastMoveCommandIdx = i\n\t\t\t}\n\n\t\t\tconst nextIdx = command.isClose\n\t\t\t\t? assertExists(lastMoveCommandIdx) + 1\n\t\t\t\t: !this.commands[i + 1] || this.commands[i + 1].type === 'move'\n\t\t\t\t\t? undefined\n\t\t\t\t\t: i + 1\n\n\t\t\tconst nextInfo =\n\t\t\t\tnextIdx !== undefined && this.commands[nextIdx] && this.commands[nextIdx]?.type !== 'move'\n\t\t\t\t\t? commandInfo[nextIdx]\n\t\t\t\t\t: undefined\n\n\t\t\tconst currentSupportsRoundness = commandsSupportingRoundness[command.type]\n\t\t\tconst nextSupportsRoundness =\n\t\t\t\tnextIdx !== undefined ? commandsSupportingRoundness[this.commands[nextIdx].type] : false\n\n\t\t\tconst currentInfo = commandInfo[i]\n\n\t\t\tconst tangentToPrev = currentInfo?.tangentEnd\n\t\t\tconst tangentToNext = nextInfo?.tangentStart\n\n\t\t\tconst roundnessClampedForAngle =\n\t\t\t\tcurrentSupportsRoundness &&\n\t\t\t\tnextSupportsRoundness &&\n\t\t\t\ttangentToPrev &&\n\t\t\t\ttangentToNext &&\n\t\t\t\tVec.Len2(tangentToPrev) > 0.01 &&\n\t\t\t\tVec.Len2(tangentToNext) > 0.01\n\t\t\t\t\t? modulate(\n\t\t\t\t\t\t\tMath.abs(Vec.AngleBetween(tangentToPrev, tangentToNext)),\n\t\t\t\t\t\t\t[Math.PI / 2, Math.PI],\n\t\t\t\t\t\t\t[roundness, 0],\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t)\n\t\t\t\t\t: 0\n\n\t\t\tconst shortestDistance = Math.min(\n\t\t\t\tcurrentInfo?.length ?? Infinity,\n\t\t\t\tnextInfo?.length ?? Infinity\n\t\t\t)\n\t\t\tconst offsetLimit = shortestDistance - roundnessClampedForAngle * 2\n\n\t\t\tconst offsetAmount = clamp(offset, 0, offsetLimit / 4)\n\n\t\t\tconst roundnessBeforeClampedForLength = Math.min(\n\t\t\t\troundnessClampedForAngle,\n\t\t\t\t(currentInfo?.length ?? Infinity) / 4\n\t\t\t)\n\t\t\tconst roundnessAfterClampedForLength = Math.min(\n\t\t\t\troundnessClampedForAngle,\n\t\t\t\t(nextInfo?.length ?? Infinity) / 4\n\t\t\t)\n\n\t\t\tconst drawCommand = {\n\t\t\t\tcommand,\n\t\t\t\toffsetAmount,\n\t\t\t\troundnessBefore: roundnessBeforeClampedForLength,\n\t\t\t\troundnessAfter: roundnessAfterClampedForLength,\n\t\t\t\ttangentToPrev: commandInfo[i]?.tangentEnd,\n\t\t\t\ttangentToNext: nextInfo?.tangentStart,\n\t\t\t\tmoveDidClose: false,\n\t\t\t}\n\n\t\t\tdrawCommands.push(drawCommand)\n\n\t\t\tif (command.isClose && lastMoveCommandIdx !== null) {\n\t\t\t\tconst lastMoveCommand = drawCommands[lastMoveCommandIdx]\n\t\t\t\tlastMoveCommand.moveDidClose = true\n\t\t\t\tlastMoveCommand.roundnessAfter = roundnessAfterClampedForLength\n\t\t\t} else if (command.type === 'move') {\n\t\t\t\tlastMoveCommandIdx = i\n\t\t\t}\n\t\t}\n\n\t\tfor (let pass = 0; pass < passes; pass++) {\n\t\t\tconst random = rng(randomSeed + pass)\n\n\t\t\tlet lastMoveToOffset = { x: 0, y: 0 }\n\t\t\tlet isSkippingCurrentLine = false\n\t\t\tfor (const {\n\t\t\t\tcommand,\n\t\t\t\toffsetAmount,\n\t\t\t\troundnessBefore,\n\t\t\t\troundnessAfter,\n\t\t\t\ttangentToNext,\n\t\t\t\ttangentToPrev,\n\t\t\t} of drawCommands) {\n\t\t\t\tconst offset = command.isClose\n\t\t\t\t\t? lastMoveToOffset\n\t\t\t\t\t: { x: random() * offsetAmount, y: random() * offsetAmount }\n\n\t\t\t\tif (command.type === 'move') {\n\t\t\t\t\tlastMoveToOffset = offset\n\t\t\t\t\tconst isFilled =\n\t\t\t\t\t\tcommand.opts?.geometry === false ? false : (command.opts?.geometry?.isFilled ?? false)\n\t\t\t\t\tif (onlyFilled && !isFilled) {\n\t\t\t\t\t\tisSkippingCurrentLine = true\n\t\t\t\t\t} else {\n\t\t\t\t\t\tisSkippingCurrentLine = false\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isSkippingCurrentLine) continue\n\n\t\t\t\tconst offsetPoint = Vec.Add(command, offset)\n\n\t\t\t\tconst endPoint =\n\t\t\t\t\ttangentToNext && roundnessAfter > 0\n\t\t\t\t\t\t? Vec.Mul(tangentToNext, -roundnessAfter).add(offsetPoint)\n\t\t\t\t\t\t: offsetPoint\n\n\t\t\t\tconst startPoint =\n\t\t\t\t\ttangentToPrev && roundnessBefore > 0\n\t\t\t\t\t\t? Vec.Mul(tangentToPrev, roundnessBefore).add(offsetPoint)\n\t\t\t\t\t\t: offsetPoint\n\n\t\t\t\tif (endPoint === offsetPoint || startPoint === offsetPoint) {\n\t\t\t\t\tswitch (command.type) {\n\t\t\t\t\t\tcase 'move':\n\t\t\t\t\t\t\tparts.push('M', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'line':\n\t\t\t\t\t\t\tparts.push('L', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'cubic': {\n\t\t\t\t\t\t\tconst offsetCp1 = Vec.Add(command.cp1, offset)\n\t\t\t\t\t\t\tconst offsetCp2 = Vec.Add(command.cp2, offset)\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'C',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch (command.type) {\n\t\t\t\t\t\tcase 'move':\n\t\t\t\t\t\t\tparts.push('M', toDomPrecision(endPoint.x), toDomPrecision(endPoint.y))\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'line':\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'L',\n\t\t\t\t\t\t\t\ttoDomPrecision(startPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(startPoint.y),\n\n\t\t\t\t\t\t\t\t'Q',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(endPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'cubic': {\n\t\t\t\t\t\t\tconst offsetCp1 = Vec.Add(command.cp1, offset)\n\t\t\t\t\t\t\tconst offsetCp2 = Vec.Add(command.cp2, offset)\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\t'C',\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp1.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetCp2.y),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.x),\n\t\t\t\t\t\t\t\ttoDomPrecision(offsetPoint.y)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn parts.join(' ')\n\t}\n\n\tprivate calculateSegmentLength(lastPoint: VecLike, command: PathBuilderCommand) {\n\t\tswitch (command.type) {\n\t\t\tcase 'move':\n\t\t\t\treturn 0\n\t\t\tcase 'line':\n\t\t\t\treturn Vec.Dist(lastPoint, command)\n\t\t\tcase 'cubic':\n\t\t\t\treturn CubicBezier.length(\n\t\t\t\t\tlastPoint.x,\n\t\t\t\t\tlastPoint.y,\n\t\t\t\t\tcommand.cp1.x,\n\t\t\t\t\tcommand.cp1.y,\n\t\t\t\t\tcommand.cp2.x,\n\t\t\t\t\tcommand.cp2.y,\n\t\t\t\t\tcommand.x,\n\t\t\t\t\tcommand.y\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t}\n\t}\n\n\t/** @internal */\n\tgetCommands(): readonly PathBuilderCommand[] {\n\t\treturn this.commands\n\t}\n\n\t/** @internal */\n\tgetCommandInfo() {\n\t\tconst commandInfo: Array<undefined | PathBuilderCommandInfo> = []\n\t\tfor (let i = 1; i < this.commands.length; i++) {\n\t\t\tconst previous = this.commands[i - 1]\n\t\t\tconst current = this.commands[i]\n\n\t\t\tif (current._info) {\n\t\t\t\tcommandInfo[i] = current._info\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (current.type === 'move') {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tlet tangentStart, tangentEnd\n\t\t\tswitch (current.type) {\n\t\t\t\tcase 'line':\n\t\t\t\t\ttangentStart = tangentEnd = Vec.Sub(previous, current).uni()\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic': {\n\t\t\t\t\ttangentStart = Vec.Sub(current.cp1, previous).uni()\n\t\t\t\t\ttangentEnd = Vec.Sub(current.cp2, current).uni()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(current, 'type')\n\t\t\t}\n\n\t\t\tcurrent._info = {\n\t\t\t\ttangentStart,\n\t\t\t\ttangentEnd,\n\t\t\t\tlength: this.calculateSegmentLength(previous, current),\n\t\t\t}\n\t\t\tcommandInfo[i] = current._info\n\t\t}\n\n\t\treturn commandInfo\n\t}\n}\n\nconst commandsSupportingRoundness = {\n\tline: true,\n\tmove: true,\n\tcubic: false,\n} as const satisfies Record<PathBuilderCommand['type'], boolean>\n\n/** @public */\nexport class PathBuilderGeometry2d extends Geometry2d {\n\tconstructor(\n\t\tprivate readonly path: PathBuilder,\n\t\tprivate readonly startIdx: number,\n\t\tprivate readonly endIdx: number,\n\t\toptions: Geometry2dOptions\n\t) {\n\t\tsuper(options)\n\t}\n\n\tprivate _segments: Geometry2d[] | null = null\n\tgetSegments() {\n\t\tif (this._segments) return this._segments\n\n\t\tthis._segments = []\n\t\tlet last = this.path.commands[this.startIdx]\n\t\tassert(last.type === 'move')\n\n\t\tfor (let i = this.startIdx + 1; i < this.endIdx; i++) {\n\t\t\tconst command = this.path.commands[i]\n\t\t\tassert(command.type !== 'move')\n\n\t\t\tswitch (command.type) {\n\t\t\t\tcase 'line':\n\t\t\t\t\tthis._segments.push(new Edge2d({ start: Vec.From(last), end: Vec.From(command) }))\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubic': {\n\t\t\t\t\tthis._segments.push(\n\t\t\t\t\t\tnew CubicBezier2d({\n\t\t\t\t\t\t\tstart: Vec.From(last),\n\t\t\t\t\t\t\tcp1: Vec.From(command.cp1),\n\t\t\t\t\t\t\tcp2: Vec.From(command.cp2),\n\t\t\t\t\t\t\tend: Vec.From(command),\n\t\t\t\t\t\t\tresolution: command.resolution,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(command, 'type')\n\t\t\t}\n\n\t\t\tlast = command\n\t\t}\n\n\t\treturn this._segments\n\t}\n\n\toverride getVertices(filters: Geometry2dFilters): Vec[] {\n\t\tconst vs = this.getSegments()\n\t\t\t.flatMap((s) => s.getVertices(filters))\n\t\t\t.filter((vertex, i, vertices) => {\n\t\t\t\tconst prev = vertices[i - 1]\n\t\t\t\tif (!prev) return true\n\t\t\t\treturn !Vec.Equals(prev, vertex)\n\t\t\t})\n\n\t\tif (this.isClosed) {\n\t\t\tconst last = vs[vs.length - 1]\n\t\t\tconst first = vs[0]\n\t\t\tif (!Vec.Equals(last, first)) {\n\t\t\t\tvs.push(first)\n\t\t\t}\n\t\t}\n\n\t\treturn vs\n\t}\n\n\toverride nearestPoint(point: VecLike, _filters?: Geometry2dFilters): Vec {\n\t\tlet nearest: Vec | null = null\n\t\tlet nearestDistance = Infinity\n\n\t\tfor (const segment of this.getSegments()) {\n\t\t\tconst candidate = segment.nearestPoint(point)\n\t\t\tconst distance = Vec.Dist2(point, candidate)\n\t\t\tif (distance < nearestDistance) {\n\t\t\t\tnearestDistance = distance\n\t\t\t\tnearest = candidate\n\t\t\t}\n\t\t}\n\n\t\tassert(nearest, 'No nearest point found')\n\t\treturn nearest\n\t}\n\n\toverride hitTestLineSegment(\n\t\tA: VecLike,\n\t\tB: VecLike,\n\t\tdistance = 0,\n\t\tfilters?: Geometry2dFilters\n\t): boolean {\n\t\treturn super.hitTestLineSegment(A, B, distance, filters)\n\t}\n\toverride getSvgPathData(): string {\n\t\treturn this.path.toD({ startIdx: this.startIdx, endIdx: this.endIdx })\n\t}\n}\n\n/*!\n * Adapted from https://github.com/adobe-webplatform/Snap.svg/tree/master\n * Apache License: https://github.com/adobe-webplatform/Snap.svg/blob/master/LICENSE\n * https://github.com/adobe-webplatform/Snap.svg/blob/c8e483c9694517e24b282f8f59f985629f4994ce/dist/snap.svg.js#L5786\n */\nconst CubicBezier = {\n\tbase3(t: number, p1: number, p2: number, p3: number, p4: number) {\n\t\tconst t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4\n\t\tconst t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3\n\t\treturn t * t2 - 3 * p1 + 3 * p2\n\t},\n\t/**\n\t * Calculate the approximate length of a cubic bezier curve from (x1, y1) to (x4, y4) with\n\t * control points (x2, y2) and (x3, y3).\n\t */\n\tlength(\n\t\tx1: number,\n\t\ty1: number,\n\t\tx2: number,\n\t\ty2: number,\n\t\tx3: number,\n\t\ty3: number,\n\t\tx4: number,\n\t\ty4: number,\n\t\tz = 1\n\t) {\n\t\tz = z > 1 ? 1 : z < 0 ? 0 : z\n\t\tconst z2 = z / 2\n\t\tconst n = 12\n\n\t\tlet sum = 0\n\t\tsum = 0\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tconst ct = z2 * CubicBezier.Tvalues[i] + z2\n\t\t\tconst xbase = CubicBezier.base3(ct, x1, x2, x3, x4)\n\t\t\tconst ybase = CubicBezier.base3(ct, y1, y2, y3, y4)\n\t\t\tconst comb = xbase * xbase + ybase * ybase\n\t\t\tsum += CubicBezier.Cvalues[i] * Math.sqrt(comb)\n\t\t}\n\t\treturn z2 * sum\n\t},\n\tTvalues: [\n\t\t-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873, -0.7699, 0.7699, -0.9041, 0.9041, -0.9816,\n\t\t0.9816,\n\t],\n\tCvalues: [\n\t\t0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032, 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472,\n\t],\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -69,6 +69,7 @@ const PlainTextLabel = import_react.default.memo(function PlainTextLabel2({
|
|
|
69
69
|
"div",
|
|
70
70
|
{
|
|
71
71
|
className: `${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`,
|
|
72
|
+
"aria-hidden": !isEditing,
|
|
72
73
|
"data-font": font,
|
|
73
74
|
"data-align": align,
|
|
74
75
|
"data-hastext": !isEmpty,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/PlainTextLabel.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n\n/**\n * @deprecated Use `PlainTextLabel` instead.\n * @public\n */\nexport const TextLabel = PlainTextLabel\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n\n/**\n * @deprecated Use `PlainTextLabel` instead.\n * @public\n */\nexport const TextLabel = PlainTextLabel\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkGG;AA1FH,mBAAkB;AAClB,2BAA8B;AAC9B,yBAA4B;AAC5B,yBAA8B;AAC9B,kCAAqC;AAgC9B,MAAM,iBAAiB,aAAAA,QAAM,KAAK,SAASC,gBAAe;AAAA,EAChE;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,EAAE,QAAQ,SAAS,WAAW,mBAAmB,GAAG,iBAAiB,QAC1E,kDAAqB,SAAS,MAAM,SAAS;AAE9C,QAAM,iBAAiB,+BAAY,oBAAoB,aAAa,EAAE;AACtE,QAAM,UAAU,eAAe,SAAS;AAExC,QAAM,kBAAc,kCAAc,KAAK;AAEvC,MAAI,CAAC,aAAa,CAAC,SAAS;AAC3B,WAAO;AAAA,EACR;AAMA,QAAM,YAAY,mBAAmB;AACrC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,GAAG,SAAS;AAAA,MACvB,eAAa,CAAC;AAAA,MACd,aAAW;AAAA,MACX,cAAY;AAAA,MACZ,gBAAc,CAAC;AAAA,MACf,kBAAgB;AAAA,MAChB,6BAA2B;AAAA,MAC3B,iBAAe,CAAC,CAAC;AAAA,MACjB,mBAAiB;AAAA,MACjB,OAAO;AAAA,QACN,gBAAgB,UAAU,YAAY,cAAc,WAAW;AAAA,QAC/D,YAAY,kBAAkB,WAAW,WAAW;AAAA,QACpD;AAAA,QACA,GAAG;AAAA,MACJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,GAAG,SAAS;AAAA,UACvB,OAAO;AAAA,YACN;AAAA,YACA,YAAY,WAAW,SAAS;AAAA,YAChC,WAAW,KAAK,MAAM,WAAW,UAAU,IAAI;AAAA,YAC/C,UAAU,KAAK,KAAK,aAAa,CAAC;AAAA,YAClC,OAAO;AAAA,YACP,OAAO,YAAY,KAAK,KAAK,SAAS,IAAI;AAAA,YAC1C,QAAQ,aAAa,KAAK,KAAK,UAAU,IAAI;AAAA,UAC9C;AAAA,UAEA;AAAA,wDAAC,SAAI,WAAW,GAAG,SAAS,4BAA4B,KAAI,QAC1D,yBAAe,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,UAC5C,4CAAC,SAAgB,KAAI,QACnB,wBADQ,KAEV,CACA,GACF;AAAA,aACE,qBAAqB,eACtB;AAAA,cAAC;AAAA;AAAA,gBAEA,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACC,GAAG;AAAA,gBACJ,eAAe,uBAAuB,iBAAiB;AAAA;AAAA,YACxD;AAAA;AAAA;AAAA,MAEF;AAAA;AAAA,EACD;AAEF,CAAC;AAMM,MAAM,YAAY;",
|
|
6
6
|
"names": ["React", "PlainTextLabel"]
|
|
7
7
|
}
|
|
@@ -103,6 +103,7 @@ const RichTextLabel = import_react.default.memo(function RichTextLabel2({
|
|
|
103
103
|
"div",
|
|
104
104
|
{
|
|
105
105
|
className: `${cssPrefix}-label tl-text-wrapper tl-rich-text-wrapper`,
|
|
106
|
+
"aria-hidden": !isEditing,
|
|
106
107
|
"data-font": font,
|
|
107
108
|
"data-align": align,
|
|
108
109
|
"data-hastext": !isEmpty,
|