@snowcone-app/canvas 0.1.0
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/LICENSE.txt +70 -0
- package/README.md +357 -0
- package/dist/CanvasStateV1-D5GzvmnY.cjs +65 -0
- package/dist/CanvasStateV1-D5GzvmnY.cjs.map +1 -0
- package/dist/CanvasStateV1-ejb4d_LM.js +3692 -0
- package/dist/CanvasStateV1-ejb4d_LM.js.map +1 -0
- package/dist/ElementFactory-B7UOaJSD.cjs +23865 -0
- package/dist/ElementFactory-B7UOaJSD.cjs.map +1 -0
- package/dist/ElementFactory-uJTXU-nP.js +29615 -0
- package/dist/ElementFactory-uJTXU-nP.js.map +1 -0
- package/dist/HybridHistoryManager-BV6XV0nD.js +8048 -0
- package/dist/HybridHistoryManager-BV6XV0nD.js.map +1 -0
- package/dist/HybridHistoryManager-BXD93pp8.cjs +8 -0
- package/dist/HybridHistoryManager-BXD93pp8.cjs.map +1 -0
- package/dist/ImportManager-BYwuK6n4.cjs +2 -0
- package/dist/ImportManager-BYwuK6n4.cjs.map +1 -0
- package/dist/ImportManager-CxiaRg1N.js +222 -0
- package/dist/ImportManager-CxiaRg1N.js.map +1 -0
- package/dist/ThemeContext-4mJ_y0Me.cjs +2 -0
- package/dist/ThemeContext-4mJ_y0Me.cjs.map +1 -0
- package/dist/ThemeContext-H0Z-MqqR.js +1077 -0
- package/dist/ThemeContext-H0Z-MqqR.js.map +1 -0
- package/dist/advanced.d.ts +2 -0
- package/dist/advanced.js +48 -0
- package/dist/advanced.js.map +1 -0
- package/dist/advanced.mjs +15679 -0
- package/dist/advanced.mjs.map +1 -0
- package/dist/api/advanced.d.ts +110 -0
- package/dist/api/internals.d.ts +39 -0
- package/dist/api/stable.d.ts +44 -0
- package/dist/api/testing.d.ts +25 -0
- package/dist/browser-module-D0gHY9rY.cjs +9 -0
- package/dist/browser-module-D0gHY9rY.cjs.map +1 -0
- package/dist/browser-module-DFvKXBUE.js +15474 -0
- package/dist/browser-module-DFvKXBUE.js.map +1 -0
- package/dist/components/ArtboardDistressPanel.d.ts +7 -0
- package/dist/components/ArtboardImageMaskPanel.d.ts +7 -0
- package/dist/components/ArtboardPropertiesToolbar.d.ts +19 -0
- package/dist/components/ArtboardToolbar.d.ts +10 -0
- package/dist/components/BackButton.d.ts +7 -0
- package/dist/components/BackgroundPickerDropdown.d.ts +11 -0
- package/dist/components/BackgroundSwitcher.d.ts +7 -0
- package/dist/components/CanvasA11yFallback.d.ts +62 -0
- package/dist/components/CanvasEditor/CanvasRendererComponent.d.ts +51 -0
- package/dist/components/CanvasEditor/handlers/cropModeHandlers.d.ts +114 -0
- package/dist/components/CanvasEditor/handlers/groupChildHandlers.d.ts +65 -0
- package/dist/components/CanvasEditor/handlers/index.d.ts +10 -0
- package/dist/components/CanvasEditor/handlers/multiSelectionHandlers.d.ts +86 -0
- package/dist/components/CanvasEditor/hooks/buildSpreadClipShape.d.ts +20 -0
- package/dist/components/CanvasEditor/hooks/index.d.ts +24 -0
- package/dist/components/CanvasEditor/hooks/useActiveChild.d.ts +23 -0
- package/dist/components/CanvasEditor/hooks/useAnimatedFocusRect.d.ts +17 -0
- package/dist/components/CanvasEditor/hooks/useCanvasInteraction.d.ts +284 -0
- package/dist/components/CanvasEditor/hooks/useCanvasLayout.d.ts +50 -0
- package/dist/components/CanvasEditor/hooks/useCanvasRenderLoop.d.ts +140 -0
- package/dist/components/CanvasEditor/hooks/useCropMode.d.ts +4 -0
- package/dist/components/CanvasEditor/hooks/useHoverState.d.ts +9 -0
- package/dist/components/CanvasEditor/hooks/useInteractionState.d.ts +23 -0
- package/dist/components/CanvasEditor/hooks/useKeyboardHandlers.d.ts +16 -0
- package/dist/components/CanvasEditor/hooks/useMarqueeSelection.d.ts +22 -0
- package/dist/components/CanvasEditor/hooks/useMultiSelection.d.ts +5 -0
- package/dist/components/CanvasEditor/hooks/usePenTool.d.ts +10 -0
- package/dist/components/CanvasEditor/hooks/useRenderState.d.ts +31 -0
- package/dist/components/CanvasEditor/hooks/useSnapAndSpacing.d.ts +42 -0
- package/dist/components/CanvasEditor/hooks/useTextEditing.d.ts +56 -0
- package/dist/components/CanvasEditor/hooks/useTextEditingHandlers.d.ts +75 -0
- package/dist/components/CanvasEditor/renderers/hoverRenderer.d.ts +12 -0
- package/dist/components/CanvasEditor/renderers/index.d.ts +10 -0
- package/dist/components/CanvasEditor/renderers/marqueeRenderer.d.ts +21 -0
- package/dist/components/CanvasEditor/renderers/multiSelectionRenderer.d.ts +52 -0
- package/dist/components/CanvasEditor/renderers/renderingConstants.d.ts +59 -0
- package/dist/components/CanvasEditor/types/index.d.ts +11 -0
- package/dist/components/CanvasEditor.d.ts +102 -0
- package/dist/components/ColorPickerDropdown.d.ts +29 -0
- package/dist/components/CompositingPanel.d.ts +8 -0
- package/dist/components/ContextualToolbars.d.ts +150 -0
- package/dist/components/CropPanel.d.ts +20 -0
- package/dist/components/DistressPanel.d.ts +7 -0
- package/dist/components/DocsPage.d.ts +6 -0
- package/dist/components/Drawer.d.ts +39 -0
- package/dist/components/EffectsPanel.d.ts +14 -0
- package/dist/components/ExportTestPanel.d.ts +16 -0
- package/dist/components/FontBrowserDrawer.d.ts +20 -0
- package/dist/components/FontSizeDropdown.d.ts +12 -0
- package/dist/components/GlyphBrowserDrawer.d.ts +13 -0
- package/dist/components/GlyphPicker.d.ts +14 -0
- package/dist/components/IconMatchTest.d.ts +3 -0
- package/dist/components/IconSizeTest.d.ts +3 -0
- package/dist/components/ImageBrowserDrawer.d.ts +27 -0
- package/dist/components/ImageToolbar.d.ts +47 -0
- package/dist/components/LayerEffects.d.ts +11 -0
- package/dist/components/LayerLeadingChip.d.ts +9 -0
- package/dist/components/LayersPanel.d.ts +30 -0
- package/dist/components/MaskItem.d.ts +12 -0
- package/dist/components/MasksPanel.d.ts +7 -0
- package/dist/components/MonotypeDemoPage.d.ts +2 -0
- package/dist/components/MoreMenu.d.ts +15 -0
- package/dist/components/OpenTypeFeaturesPanel.d.ts +12 -0
- package/dist/components/PathToolbar.d.ts +10 -0
- package/dist/components/PenToolDemo.d.ts +3 -0
- package/dist/components/ProgressiveBlur.d.ts +25 -0
- package/dist/components/RotationHandle.d.ts +47 -0
- package/dist/components/SaveLoadMenu.d.ts +15 -0
- package/dist/components/ShapeToolbar.d.ts +71 -0
- package/dist/components/ShapeTypeDrawer.d.ts +10 -0
- package/dist/components/StrokePanel.d.ts +7 -0
- package/dist/components/TailwindDemo.d.ts +3 -0
- package/dist/components/TextEffectsDropdown.d.ts +14 -0
- package/dist/components/TextToolbar.d.ts +47 -0
- package/dist/components/TextTypeDrawer.d.ts +8 -0
- package/dist/components/ThemeToggle.d.ts +2 -0
- package/dist/components/TransformControlPanel.d.ts +12 -0
- package/dist/components/VisualGuideOverlay.d.ts +156 -0
- package/dist/components/embed/ArtboardTabs.d.ts +74 -0
- package/dist/components/embed/Canvas.d.ts +72 -0
- package/dist/components/embed/EffectsPanel.d.ts +76 -0
- package/dist/components/embed/ErrorBoundary.d.ts +34 -0
- package/dist/components/embed/ExportPanel.d.ts +51 -0
- package/dist/components/embed/GlyphPanel.d.ts +70 -0
- package/dist/components/embed/ImagePanel.d.ts +58 -0
- package/dist/components/embed/LayersPanel.d.ts +13 -0
- package/dist/components/embed/LoadingStates.d.ts +32 -0
- package/dist/components/embed/MenuButton.d.ts +47 -0
- package/dist/components/embed/SnowconeCanvas.d.ts +844 -0
- package/dist/components/embed/ZoomControls.d.ts +16 -0
- package/dist/components/embed/index.d.ts +129 -0
- package/dist/components/embed/primitives/index.d.ts +42 -0
- package/dist/components/embed/ui/index.d.ts +52 -0
- package/dist/components/embed/utils/index.d.ts +31 -0
- package/dist/components/embedded/ArtboardEmbed.d.ts +70 -0
- package/dist/components/embedded/MerchifyThemeWrapper.d.ts +30 -0
- package/dist/components/embedded/ProductPreviewCard.d.ts +8 -0
- package/dist/components/embedded/index.d.ts +7 -0
- package/dist/components/primitives/ButtonGroup.d.ts +27 -0
- package/dist/components/primitives/ControlGroup.d.ts +15 -0
- package/dist/components/primitives/Dropdown.d.ts +27 -0
- package/dist/components/primitives/DropdownMenu.d.ts +9 -0
- package/dist/components/primitives/MenuItem.d.ts +13 -0
- package/dist/components/primitives/Panel.d.ts +25 -0
- package/dist/components/primitives/SecondaryToolbar.d.ts +9 -0
- package/dist/components/primitives/Switch.d.ts +10 -0
- package/dist/components/primitives/Toggle.d.ts +17 -0
- package/dist/components/primitives/index.d.ts +22 -0
- package/dist/components/stories/utils/MockEditorProvider.d.ts +32 -0
- package/dist/components/stories/utils/QACanvasCard.d.ts +41 -0
- package/dist/components/stories/utils/VisualQACard.d.ts +24 -0
- package/dist/components/stories/utils/element-factories.d.ts +188 -0
- package/dist/components/stories/utils/spec-to-elements.d.ts +74 -0
- package/dist/components/stories/utils/themeDecorator.d.ts +45 -0
- package/dist/components/stories/utils/unified-test-cases.d.ts +27 -0
- package/dist/components/text-toolbar/BoldButton.d.ts +5 -0
- package/dist/components/text-toolbar/FontColorButton.d.ts +6 -0
- package/dist/components/text-toolbar/FontSizeGroup.d.ts +5 -0
- package/dist/components/text-toolbar/ItalicButton.d.ts +5 -0
- package/dist/components/text-toolbar/TextAlignButton.d.ts +5 -0
- package/dist/components/text-toolbar/TextMoreMenu.d.ts +7 -0
- package/dist/components/text-toolbar/UnderlineButton.d.ts +5 -0
- package/dist/components/text-toolbar/UppercaseButton.d.ts +5 -0
- package/dist/components/text-toolbar/index.d.ts +25 -0
- package/dist/components/toolbars/EmbeddedToolbarLayout.d.ts +49 -0
- package/dist/components/toolbars/ExpandedPanelIcon.d.ts +13 -0
- package/dist/components/toolbars/FloatingPanels.d.ts +23 -0
- package/dist/components/toolbars/GroupElementToolbar.d.ts +35 -0
- package/dist/components/toolbars/SecondaryPanels.d.ts +125 -0
- package/dist/components/toolbars/index.d.ts +18 -0
- package/dist/components/toolbars/shared/ColorPanelWrapper.d.ts +9 -0
- package/dist/components/toolbars/shared/SecondaryPanelWrapper.d.ts +9 -0
- package/dist/components/ui/PresetCarousel.d.ts +21 -0
- package/dist/components/ui/SecondaryPanel.d.ts +28 -0
- package/dist/components/ui/SliderRow.d.ts +30 -0
- package/dist/components/ui/collapsed-toolbar-header.d.ts +14 -0
- package/dist/components/ui/custom-icons.d.ts +25 -0
- package/dist/components/ui/icons.d.ts +100 -0
- package/dist/components/ui/index.d.ts +48 -0
- package/dist/components/ui/normalized-icon.d.ts +63 -0
- package/dist/components/ui/toolbar-button.d.ts +24 -0
- package/dist/compose-Bo108juW.cjs +33 -0
- package/dist/compose-Bo108juW.cjs.map +1 -0
- package/dist/compose-DQ1FZS3O.js +7690 -0
- package/dist/compose-DQ1FZS3O.js.map +1 -0
- package/dist/constants.d.ts +121 -0
- package/dist/contexts/CommandContext.d.ts +87 -0
- package/dist/contexts/EditorContext.d.ts +190 -0
- package/dist/contexts/ElementsContext.d.ts +104 -0
- package/dist/contexts/HistoryContext.d.ts +60 -0
- package/dist/contexts/KitContext.d.ts +50 -0
- package/dist/contexts/SelectionContext.d.ts +51 -0
- package/dist/contexts/ThemeContext.d.ts +55 -0
- package/dist/contexts/ToolStateContext.d.ts +60 -0
- package/dist/contexts/ViewportContext.d.ts +87 -0
- package/dist/core/AlignmentSnapSystem.d.ts +270 -0
- package/dist/core/ArtboardElement.d.ts +106 -0
- package/dist/core/ArtboardManager.d.ts +130 -0
- package/dist/core/ArtboardRenderer.d.ts +97 -0
- package/dist/core/BaseElement.d.ts +94 -0
- package/dist/core/CanvasRenderer.d.ts +237 -0
- package/dist/core/CommandHistory.d.ts +173 -0
- package/dist/core/CoordinateTransform.d.ts +69 -0
- package/dist/core/CropModeController.d.ts +90 -0
- package/dist/core/EditModeRenderer.d.ts +51 -0
- package/dist/core/ElementFactory.d.ts +73 -0
- package/dist/core/ElementStore.d.ts +69 -0
- package/dist/core/EventBus.d.ts +163 -0
- package/dist/core/GeometryUtils.d.ts +247 -0
- package/dist/core/GroupElement.d.ts +134 -0
- package/dist/core/HoverRenderer.d.ts +103 -0
- package/dist/core/HybridHistoryManager.d.ts +137 -0
- package/dist/core/ImageCache.d.ts +63 -0
- package/dist/core/ImageElement.d.ts +226 -0
- package/dist/core/ImageLoadEvents.d.ts +23 -0
- package/dist/core/InteractionFeedbackRenderer.d.ts +15 -0
- package/dist/core/InteractionStateMachine.d.ts +199 -0
- package/dist/core/PathElement.d.ts +84 -0
- package/dist/core/PenToolManager.d.ts +112 -0
- package/dist/core/PinchHandler.d.ts +32 -0
- package/dist/core/ResizeHandler.d.ts +51 -0
- package/dist/core/ResizePipeline.d.ts +83 -0
- package/dist/core/ResizeUtils.d.ts +17 -0
- package/dist/core/RotationAnchorResolver.d.ts +60 -0
- package/dist/core/RotationUtils.d.ts +28 -0
- package/dist/core/SelectionRenderer.d.ts +24 -0
- package/dist/core/ShapeElement.d.ts +121 -0
- package/dist/core/SpacingSystem.d.ts +73 -0
- package/dist/core/SpatialGrid.d.ts +53 -0
- package/dist/core/TextElement.d.ts +80 -0
- package/dist/core/TextMetrics.d.ts +117 -0
- package/dist/core/Transform.d.ts +158 -0
- package/dist/core/TransformConverter.d.ts +16 -0
- package/dist/core/TransformHandles.d.ts +55 -0
- package/dist/core/artboardReducer.d.ts +46 -0
- package/dist/effects/DistressGenerator.d.ts +26 -0
- package/dist/effects/DistressTextureCache.d.ts +49 -0
- package/dist/effects/distress-presets.d.ts +86 -0
- package/dist/effects/distress-textures.d.ts +34 -0
- package/dist/effects/distress-utils.d.ts +39 -0
- package/dist/effects/mask-presets.d.ts +36 -0
- package/dist/fonts/google-fonts.d.ts +48 -0
- package/dist/google-fonts.json +1 -0
- package/dist/hooks/index.d.ts +42 -0
- package/dist/hooks/useArtboards.d.ts +71 -0
- package/dist/hooks/useAutoExport.d.ts +66 -0
- package/dist/hooks/useBreakpoint.d.ts +53 -0
- package/dist/hooks/useCanvasEvents.d.ts +8 -0
- package/dist/hooks/useCanvasReady.d.ts +22 -0
- package/dist/hooks/useClickOutside.d.ts +3 -0
- package/dist/hooks/useCommandHistory.d.ts +39 -0
- package/dist/hooks/useCommands.d.ts +47 -0
- package/dist/hooks/useContentReady.d.ts +18 -0
- package/dist/hooks/useElementById.d.ts +20 -0
- package/dist/hooks/useElementByName.d.ts +10 -0
- package/dist/hooks/useElementProperties.d.ts +29 -0
- package/dist/hooks/useExport.d.ts +89 -0
- package/dist/hooks/useImageBinding.d.ts +34 -0
- package/dist/hooks/useKeyboardShortcuts.d.ts +13 -0
- package/dist/hooks/useLayerDndKit.d.ts +24 -0
- package/dist/hooks/useLayerDragDrop.d.ts +58 -0
- package/dist/hooks/useLayerPreview.d.ts +31 -0
- package/dist/hooks/useLayerSelection.d.ts +76 -0
- package/dist/hooks/useLayers.d.ts +91 -0
- package/dist/hooks/usePerformance.d.ts +48 -0
- package/dist/hooks/useProjectLoader.d.ts +64 -0
- package/dist/hooks/useSelectedElement.d.ts +17 -0
- package/dist/hooks/useTextBinding.d.ts +26 -0
- package/dist/hooks/useTextToolbar.d.ts +61 -0
- package/dist/hooks/useViewport.d.ts +46 -0
- package/dist/icons/icon-data.d.ts +2 -0
- package/dist/icons/registry.d.ts +28 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1138 -0
- package/dist/index.mjs.map +1 -0
- package/dist/internals.d.ts +2 -0
- package/dist/internals.js +2 -0
- package/dist/internals.js.map +1 -0
- package/dist/internals.mjs +219 -0
- package/dist/internals.mjs.map +1 -0
- package/dist/kits/compose.d.ts +69 -0
- package/dist/kits/index.d.ts +21 -0
- package/dist/kits/presets.d.ts +40 -0
- package/dist/kits/registry.d.ts +33 -0
- package/dist/kits/sections.d.ts +119 -0
- package/dist/kits/serialization.d.ts +78 -0
- package/dist/kits/types.d.ts +129 -0
- package/dist/kits/validation.d.ts +36 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/plugins/ElementTypePlugin.d.ts +90 -0
- package/dist/presets/artboard-color-presets.d.ts +22 -0
- package/dist/presets/tshirt-presets.d.ts +60 -0
- package/dist/rendering/CompositingRenderer.d.ts +33 -0
- package/dist/rendering/DistressTextureRenderer.d.ts +39 -0
- package/dist/rendering/ElementRenderUtils.d.ts +17 -0
- package/dist/rendering/MaskRenderer.d.ts +41 -0
- package/dist/rendering/PieceGuideRenderer.d.ts +177 -0
- package/dist/rendering/StrokeRenderer.d.ts +24 -0
- package/dist/rendering/canvas-renderer.d.ts +18 -0
- package/dist/rendering/element-serializer.d.ts +143 -0
- package/dist/rendering/image-renderer.d.ts +6 -0
- package/dist/rendering/knockout-utils.d.ts +48 -0
- package/dist/rendering/mask-utils.d.ts +65 -0
- package/dist/rendering/renderer-types.d.ts +79 -0
- package/dist/rendering/rich-text-renderer.d.ts +43 -0
- package/dist/rendering/serialize-for-server.d.ts +45 -0
- package/dist/rendering/shape-renderer.d.ts +6 -0
- package/dist/rendering/stroke-utils.d.ts +18 -0
- package/dist/rendering/text-renderer.d.ts +71 -0
- package/dist/rendering/transform-renderer.d.ts +33 -0
- package/dist/services/AutoExportManager.d.ts +107 -0
- package/dist/services/falApi.d.ts +63 -0
- package/dist/services/nounProjectApi.d.ts +90 -0
- package/dist/services/recraftApi.d.ts +65 -0
- package/dist/services/runwareApi.d.ts +69 -0
- package/dist/state/CanvasStateV1.d.ts +373 -0
- package/dist/state/index.d.ts +10 -0
- package/dist/style.css +1 -0
- package/dist/taco-reference-cropped.jpg +0 -0
- package/dist/testing/MockEditorProvider.d.ts +49 -0
- package/dist/testing/index.d.ts +25 -0
- package/dist/testing/utils.d.ts +128 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +2 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +140 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/textures/glass-frame.svg +32 -0
- package/dist/theme.d.ts +99 -0
- package/dist/themes/index.d.ts +23 -0
- package/dist/transforms/ArchTransform.d.ts +14 -0
- package/dist/transforms/AscendTransform.d.ts +14 -0
- package/dist/transforms/CircleTransform.d.ts +51 -0
- package/dist/transforms/CustomTransform.d.ts +81 -0
- package/dist/transforms/FlagTransform.d.ts +14 -0
- package/dist/transforms/LeanTransform.d.ts +14 -0
- package/dist/transforms/WaveTransform.d.ts +16 -0
- package/dist/transforms/defaults.d.ts +33 -0
- package/dist/transforms/index.d.ts +10 -0
- package/dist/transforms/registry.d.ts +51 -0
- package/dist/types/capabilities.d.ts +50 -0
- package/dist/types/guards.d.ts +31 -0
- package/dist/types/index.d.ts +765 -0
- package/dist/types/public.d.ts +31 -0
- package/dist/types/react.d.ts +132 -0
- package/dist/utils/ArtworkPlacement.d.ts +97 -0
- package/dist/utils/ElementPreviewRenderer.d.ts +19 -0
- package/dist/utils/ExportManager.d.ts +208 -0
- package/dist/utils/FontAnalyzer.d.ts +137 -0
- package/dist/utils/GlyphRenderer.d.ts +55 -0
- package/dist/utils/GoogleFontsService.d.ts +37 -0
- package/dist/utils/ImageLoader.d.ts +124 -0
- package/dist/utils/ImportManager.d.ts +72 -0
- package/dist/utils/MonotypeCategoryMapping.d.ts +36 -0
- package/dist/utils/MonotypeService.d.ts +148 -0
- package/dist/utils/PerformanceMonitor.d.ts +54 -0
- package/dist/utils/TextureManager.d.ts +60 -0
- package/dist/utils/UnifiedFontService.d.ts +117 -0
- package/dist/utils/WorkerExportManager.d.ts +185 -0
- package/dist/utils/clickProtection.d.ts +39 -0
- package/dist/utils/cn.d.ts +4 -0
- package/dist/utils/colorConversion.d.ts +101 -0
- package/dist/utils/documentColors.d.ts +108 -0
- package/dist/utils/featureApplied.d.ts +14 -0
- package/dist/utils/google-fonts-loader.d.ts +67 -0
- package/dist/utils/logger.d.ts +66 -0
- package/dist/utils/selectionPreservation.d.ts +42 -0
- package/dist/utils/textCursorUtils.d.ts +39 -0
- package/dist/utils/textUtils.d.ts +11 -0
- package/dist/workers/export-protocol.d.ts +119 -0
- package/dist/workers/export-worker.bundle.string.d.ts +2 -0
- package/dist/workers/export-worker.d.ts +5 -0
- package/package.json +201 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { BaseElement } from './BaseElement.js';
|
|
2
|
+
import { ImageTransformData, ImageElementConfig, ResizeAnchor, BoundingBox, Point, TransformStartData } from '../types/index.js';
|
|
3
|
+
/** Image loading state for retry logic and UI feedback */
|
|
4
|
+
export type ImageLoadState = 'loading' | 'loaded' | 'error' | 'retrying';
|
|
5
|
+
export declare class ImageElement extends BaseElement {
|
|
6
|
+
transformType: 'image';
|
|
7
|
+
transformData: ImageTransformData;
|
|
8
|
+
imageUrl: string;
|
|
9
|
+
imageLoaded: boolean;
|
|
10
|
+
imageElement: HTMLImageElement | null;
|
|
11
|
+
imageAspectRatio: number;
|
|
12
|
+
isCropping: boolean;
|
|
13
|
+
onLoadCallback: ((element: ImageElement) => void) | null;
|
|
14
|
+
isSvg: boolean;
|
|
15
|
+
preserveDimensions: boolean;
|
|
16
|
+
imageLoadState: ImageLoadState;
|
|
17
|
+
imageLoadError: Error | null;
|
|
18
|
+
private svgBlobUrl;
|
|
19
|
+
private loadTimeoutId;
|
|
20
|
+
private retryAttempt;
|
|
21
|
+
private cachedImageUrl;
|
|
22
|
+
constructor(config?: Partial<ImageElementConfig>);
|
|
23
|
+
/**
|
|
24
|
+
* Load image from URL
|
|
25
|
+
* For SVG files, we render to a high-DPI canvas to maintain quality
|
|
26
|
+
*/
|
|
27
|
+
loadImage(url: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Load regular raster image (PNG, JPG, etc.) with timeout and retry logic.
|
|
30
|
+
* Uses exponential backoff: 1s, 2s, 4s between retries.
|
|
31
|
+
*/
|
|
32
|
+
private loadRegularImage;
|
|
33
|
+
/**
|
|
34
|
+
* Single attempt to load a regular image with timeout.
|
|
35
|
+
* Called by loadRegularImage and retry logic.
|
|
36
|
+
*
|
|
37
|
+
* Uses the shared ImageCache to avoid duplicate loading of the same URL
|
|
38
|
+
* across multiple ImageElement instances.
|
|
39
|
+
*/
|
|
40
|
+
private attemptLoadRegularImage;
|
|
41
|
+
/**
|
|
42
|
+
* Handle a load failure - either retry with backoff or set error state.
|
|
43
|
+
*/
|
|
44
|
+
private handleLoadFailure;
|
|
45
|
+
/**
|
|
46
|
+
* Clear any pending load timeout
|
|
47
|
+
*/
|
|
48
|
+
private clearLoadTimeout;
|
|
49
|
+
/**
|
|
50
|
+
* Release the current image from the shared cache.
|
|
51
|
+
* Called when switching URLs or destroying the element.
|
|
52
|
+
*/
|
|
53
|
+
private releaseImageCache;
|
|
54
|
+
/**
|
|
55
|
+
* Manually retry loading the image after a failure.
|
|
56
|
+
* Resets retry count and starts fresh.
|
|
57
|
+
*/
|
|
58
|
+
retryImageLoad(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Revoke any existing SVG blob URL to prevent memory leaks
|
|
61
|
+
* iOS Safari has strict blob URL limits; this prevents accumulation
|
|
62
|
+
*/
|
|
63
|
+
private revokeSvgBlobUrl;
|
|
64
|
+
/**
|
|
65
|
+
* Load SVG and convert to high-DPI canvas for crisp rendering
|
|
66
|
+
* SVG is rendered at 4x resolution to maintain quality when scaled
|
|
67
|
+
*/
|
|
68
|
+
private loadSvgAsHighDpi;
|
|
69
|
+
/**
|
|
70
|
+
* Get bounding box in world coordinates
|
|
71
|
+
* Returns the unrotated dimensions - rotation is handled by the renderer
|
|
72
|
+
* When not in crop mode, returns only the cropped area dimensions
|
|
73
|
+
*/
|
|
74
|
+
getBoundingBox(): BoundingBox;
|
|
75
|
+
/**
|
|
76
|
+
* Get visual bounding box - returns the cropped area bounds
|
|
77
|
+
* This is used for group bounds calculation and should represent the visible area
|
|
78
|
+
*/
|
|
79
|
+
getVisualBoundingBox(): BoundingBox;
|
|
80
|
+
/**
|
|
81
|
+
* Get rotation anchor (center of the visible image area)
|
|
82
|
+
* In crop mode: returns the center of the full frame
|
|
83
|
+
* Not in crop mode: returns this.x, this.y (center of cropped area)
|
|
84
|
+
*/
|
|
85
|
+
getRotationAnchor(): Point;
|
|
86
|
+
/**
|
|
87
|
+
* Hit test for image - checks if point is inside the visible (cropped) area
|
|
88
|
+
*/
|
|
89
|
+
hitTest(worldX: number, worldY: number): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Render the image
|
|
92
|
+
*/
|
|
93
|
+
render(ctx: CanvasRenderingContext2D, _isSelected?: boolean, _isHovered?: boolean): void;
|
|
94
|
+
/**
|
|
95
|
+
* Render placeholder based on current image load state.
|
|
96
|
+
* Shows different visuals for loading, retrying, error, and no-image states.
|
|
97
|
+
*/
|
|
98
|
+
renderPlaceholder(ctx: CanvasRenderingContext2D): void;
|
|
99
|
+
/**
|
|
100
|
+
* Handle resize - maintain aspect ratio
|
|
101
|
+
* @returns {boolean} true if resize was applied
|
|
102
|
+
*/
|
|
103
|
+
resize(anchor: ResizeAnchor, newWidth: number, newHeight: number, startData: TransformStartData): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Get enabled anchors - only corner handles for images
|
|
106
|
+
*/
|
|
107
|
+
getEnabledAnchors(): ResizeAnchor[];
|
|
108
|
+
/**
|
|
109
|
+
* Enter crop mode
|
|
110
|
+
* Just sets the flag - position stays at the cropped area center
|
|
111
|
+
*/
|
|
112
|
+
enterCropMode(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Exit crop mode
|
|
115
|
+
* Just clears the flag - position stays the same
|
|
116
|
+
*/
|
|
117
|
+
exitCropMode(): void;
|
|
118
|
+
/**
|
|
119
|
+
* Get crop box bounds in local coordinates (before rotation)
|
|
120
|
+
* Returns the rectangle where the crop box should be rendered
|
|
121
|
+
* Local coordinates are relative to this.x, this.y (the center of the cropped area)
|
|
122
|
+
*/
|
|
123
|
+
getCropBoxBounds(): BoundingBox | null;
|
|
124
|
+
/**
|
|
125
|
+
* Get crop box corners in world coordinates (accounting for rotation)
|
|
126
|
+
* Returns array of {x, y} points for each corner
|
|
127
|
+
*/
|
|
128
|
+
getCropBoxWorldCorners(): Point[] | null;
|
|
129
|
+
/**
|
|
130
|
+
* Convert world coordinates to local coordinates (accounting for rotation and flips)
|
|
131
|
+
* Local coordinates are relative to this.x, this.y (the center of the visible area)
|
|
132
|
+
*/
|
|
133
|
+
worldToLocal(worldX: number, worldY: number): Point;
|
|
134
|
+
/**
|
|
135
|
+
* Convert local coordinates to world coordinates (accounting for rotation and flips)
|
|
136
|
+
* Inverse of worldToLocal
|
|
137
|
+
* Canvas transformations are applied in reverse: scale -> rotate -> translate
|
|
138
|
+
*/
|
|
139
|
+
localToWorld(localX: number, localY: number): Point;
|
|
140
|
+
/**
|
|
141
|
+
* Hit test for crop box handles in world coordinates
|
|
142
|
+
* Returns {type: 'corner'|'edge', anchor: string} if hit, null otherwise
|
|
143
|
+
* @param worldX - X coordinate in world space
|
|
144
|
+
* @param worldY - Y coordinate in world space
|
|
145
|
+
* @param zoom - Current zoom level (used to scale hit areas for consistent interaction)
|
|
146
|
+
*/
|
|
147
|
+
hitTestCropHandle(worldX: number, worldY: number, zoom?: number): {
|
|
148
|
+
type: 'corner' | 'edge';
|
|
149
|
+
anchor: string;
|
|
150
|
+
worldX: number;
|
|
151
|
+
worldY: number;
|
|
152
|
+
} | null;
|
|
153
|
+
/**
|
|
154
|
+
* Hit test for inside crop box in world coordinates
|
|
155
|
+
* Used for dragging the image within the crop area
|
|
156
|
+
*/
|
|
157
|
+
hitTestCropBox(worldX: number, worldY: number): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Update crop box (normalized 0-1 coordinates)
|
|
160
|
+
* @param {number} cropX - Normalized X position (0-1)
|
|
161
|
+
* @param {number} cropY - Normalized Y position (0-1)
|
|
162
|
+
* @param {number} cropWidth - Normalized width (0-1)
|
|
163
|
+
* @param {number} cropHeight - Normalized height (0-1)
|
|
164
|
+
* @param {boolean} adjustPosition - Whether to adjust this.x, this.y to keep visual position stable (default: false)
|
|
165
|
+
*/
|
|
166
|
+
updateCrop(cropX: number, cropY: number, cropWidth: number, cropHeight: number, adjustPosition?: boolean): void;
|
|
167
|
+
/**
|
|
168
|
+
* Get the local position of the corner opposite to the given anchor
|
|
169
|
+
* Corners are relative to frame center
|
|
170
|
+
*/
|
|
171
|
+
private getOppositeCornerLocalPosition;
|
|
172
|
+
/**
|
|
173
|
+
* Calculate frame center position from crop center position
|
|
174
|
+
* In crop mode, this.x/y is the crop center, not the frame center
|
|
175
|
+
*/
|
|
176
|
+
private calculateFrameCenterFromCropCenter;
|
|
177
|
+
/**
|
|
178
|
+
* Get the position of the fixed corner (opposite of anchor) in world coordinates
|
|
179
|
+
*/
|
|
180
|
+
private getFixedCornerWorldPosition;
|
|
181
|
+
/**
|
|
182
|
+
* Calculate where the frame center would be after resize
|
|
183
|
+
* The opposite corner from the anchor stays fixed in world space
|
|
184
|
+
*/
|
|
185
|
+
private calculateFrameCenterAfterResize;
|
|
186
|
+
/**
|
|
187
|
+
* Calculate crop state (position and size in normalized coords) at a given scale
|
|
188
|
+
* This is the core geometric calculation that determines where the crop zone
|
|
189
|
+
* would be positioned within the frame after resize.
|
|
190
|
+
*/
|
|
191
|
+
private calculateCropStateAtScale;
|
|
192
|
+
/**
|
|
193
|
+
* Check if a given scale keeps crop within frame bounds
|
|
194
|
+
*/
|
|
195
|
+
private isScaleValidForCropBounds;
|
|
196
|
+
/**
|
|
197
|
+
* Calculate minimum scale that keeps crop within frame bounds
|
|
198
|
+
* Uses binary search to find the largest scale >= proposedScale that satisfies constraints
|
|
199
|
+
*/
|
|
200
|
+
private calculateMinScaleForCropBounds;
|
|
201
|
+
/**
|
|
202
|
+
* Remap anchor to account for flips
|
|
203
|
+
*/
|
|
204
|
+
private remapAnchorForFlips;
|
|
205
|
+
/**
|
|
206
|
+
* Clone this element
|
|
207
|
+
*/
|
|
208
|
+
clone(): ImageElement;
|
|
209
|
+
/**
|
|
210
|
+
* Serialize to JSON
|
|
211
|
+
*/
|
|
212
|
+
toJSON(): ImageElementConfig & {
|
|
213
|
+
id: string;
|
|
214
|
+
type: 'image';
|
|
215
|
+
x: number;
|
|
216
|
+
y: number;
|
|
217
|
+
rotation: number;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Clean up resources held by this element
|
|
221
|
+
* Call this when the element is being removed from the canvas to prevent memory leaks
|
|
222
|
+
* Particularly important for iOS Safari which has strict memory limits
|
|
223
|
+
*/
|
|
224
|
+
destroy(): void;
|
|
225
|
+
}
|
|
226
|
+
export default ImageElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageLoadEvents - Simple event system for notifying when images finish loading
|
|
3
|
+
*
|
|
4
|
+
* This solves the issue where the canvas shows "Loading..." even after an image
|
|
5
|
+
* has loaded, because React doesn't know the element's internal state changed.
|
|
6
|
+
*
|
|
7
|
+
* When ImageElement finishes loading an image, it emits an event.
|
|
8
|
+
* CanvasEditor subscribes to this event and triggers a re-render.
|
|
9
|
+
*/
|
|
10
|
+
type ImageLoadListener = (elementId: string) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Subscribe to image load events
|
|
13
|
+
* @param listener - Callback called when any ImageElement finishes loading
|
|
14
|
+
* @returns Unsubscribe function
|
|
15
|
+
*/
|
|
16
|
+
export declare function subscribeToImageLoads(listener: ImageLoadListener): () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Emit an image load event
|
|
19
|
+
* Called by ImageElement when an image finishes loading
|
|
20
|
+
* @param elementId - The ID of the element that finished loading
|
|
21
|
+
*/
|
|
22
|
+
export declare function emitImageLoaded(elementId: string): void;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SnapGuide, SpacingIndicator } from '../types/index.js';
|
|
2
|
+
export declare class InteractionFeedbackRenderer {
|
|
3
|
+
/**
|
|
4
|
+
* Render snap guides layer
|
|
5
|
+
*/
|
|
6
|
+
static renderSnapGuidesLayer(ctx: CanvasRenderingContext2D, snapGuides?: SnapGuide[]): void;
|
|
7
|
+
/**
|
|
8
|
+
* Render spacing indicators layer
|
|
9
|
+
*/
|
|
10
|
+
static renderSpacingIndicatorsLayer(ctx: CanvasRenderingContext2D, spacingIndicators?: SpacingIndicator[]): void;
|
|
11
|
+
/**
|
|
12
|
+
* Render a distance label with background
|
|
13
|
+
*/
|
|
14
|
+
static renderDistanceLabel(ctx: CanvasRenderingContext2D, x: number, y: number, distance: number): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { BaseElement } from './BaseElement.js';
|
|
2
|
+
import { GroupElement } from './GroupElement.js';
|
|
3
|
+
import { ResizePipeline } from './ResizePipeline.js';
|
|
4
|
+
import { ResizeAnchor, BoundingBox, Point, InteractionMode, TransformStartData } from '../types/index.js';
|
|
5
|
+
type State = 'IDLE' | 'DRAGGING' | 'RESIZING' | 'ROTATING' | 'PINCHING';
|
|
6
|
+
interface HandleInfo {
|
|
7
|
+
anchor: ResizeAnchor;
|
|
8
|
+
type?: string;
|
|
9
|
+
cursor?: string;
|
|
10
|
+
x?: number;
|
|
11
|
+
y?: number;
|
|
12
|
+
}
|
|
13
|
+
interface RotationStartData {
|
|
14
|
+
startAngle: number;
|
|
15
|
+
currentRotation: number;
|
|
16
|
+
elementData: TransformStartData;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Output of `updatePinch` — the raw gesture state. PinchHandler
|
|
20
|
+
* consumes this together with the element snapshot in
|
|
21
|
+
* `getPinchContext()` to produce the next element.
|
|
22
|
+
*/
|
|
23
|
+
export interface PinchGesture {
|
|
24
|
+
/** Distance ratio (current / start). 1.0 = no scale change. */
|
|
25
|
+
scale: number;
|
|
26
|
+
/** Angle delta in radians (current - start). 0 = no rotate change. */
|
|
27
|
+
rotationDelta: number;
|
|
28
|
+
/** Gesture centroid at start (world coords). */
|
|
29
|
+
startCentroid: Point;
|
|
30
|
+
/** Gesture centroid right now (world coords). */
|
|
31
|
+
currentCentroid: Point;
|
|
32
|
+
}
|
|
33
|
+
interface InteractionContextData {
|
|
34
|
+
mode: InteractionMode | null;
|
|
35
|
+
dragMode?: string | null;
|
|
36
|
+
startX: number;
|
|
37
|
+
startY: number;
|
|
38
|
+
startData: TransformStartData | RotationStartData | null;
|
|
39
|
+
activeHandle: HandleInfo | null;
|
|
40
|
+
element: BaseElement | null;
|
|
41
|
+
}
|
|
42
|
+
interface SnapHandler {
|
|
43
|
+
snapPosition?: (position: Point, element: BaseElement, allElements: BaseElement[] | null) => Point;
|
|
44
|
+
snapRotation?: (rotation: number, element: BaseElement) => number;
|
|
45
|
+
}
|
|
46
|
+
export interface ActiveChildContext {
|
|
47
|
+
group: GroupElement;
|
|
48
|
+
childId: string;
|
|
49
|
+
}
|
|
50
|
+
export interface CropGroupContext {
|
|
51
|
+
group: BaseElement;
|
|
52
|
+
childIndex: number;
|
|
53
|
+
}
|
|
54
|
+
export declare class InteractionStateMachine {
|
|
55
|
+
state: State;
|
|
56
|
+
context: InteractionContextData;
|
|
57
|
+
snapHandler: SnapHandler | null;
|
|
58
|
+
resizePipeline: ResizePipeline | null;
|
|
59
|
+
/** Context for interactions targeting a child within a group */
|
|
60
|
+
_activeChildContext?: ActiveChildContext;
|
|
61
|
+
/** Context for crop mode interactions on group children */
|
|
62
|
+
_cropGroupContext?: CropGroupContext;
|
|
63
|
+
constructor(resizePipeline?: ResizePipeline | null);
|
|
64
|
+
/**
|
|
65
|
+
* Set snap handler for position/dimension snapping
|
|
66
|
+
*/
|
|
67
|
+
setSnapHandler(handler: SnapHandler | null): void;
|
|
68
|
+
/**
|
|
69
|
+
* Set resize pipeline for hooking into resize operations
|
|
70
|
+
*/
|
|
71
|
+
setResizePipeline(pipeline: ResizePipeline | null): void;
|
|
72
|
+
/**
|
|
73
|
+
* Get current state
|
|
74
|
+
*/
|
|
75
|
+
getState(): State;
|
|
76
|
+
/**
|
|
77
|
+
* Get current context
|
|
78
|
+
*/
|
|
79
|
+
getContext(): InteractionContextData;
|
|
80
|
+
/**
|
|
81
|
+
* Check if currently interacting
|
|
82
|
+
*/
|
|
83
|
+
isInteracting(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Start drag operation
|
|
86
|
+
*/
|
|
87
|
+
startDrag(element: BaseElement, mouseX: number, mouseY: number, dragMode?: string | null): void;
|
|
88
|
+
/**
|
|
89
|
+
* Get drag mode
|
|
90
|
+
*/
|
|
91
|
+
getDragMode(): string | null | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Reset drag start position (for incremental dragging)
|
|
94
|
+
*/
|
|
95
|
+
resetDragStart(mouseX: number, mouseY: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Update drag operation
|
|
98
|
+
* Returns updated position { x, y }
|
|
99
|
+
*/
|
|
100
|
+
updateDrag(mouseX: number, mouseY: number, allElements?: BaseElement[] | null): Point;
|
|
101
|
+
/**
|
|
102
|
+
* Start resize operation
|
|
103
|
+
*/
|
|
104
|
+
startResize(element: BaseElement, handle: HandleInfo, mouseX: number, mouseY: number, bbox: BoundingBox, visualBbox: BoundingBox): void;
|
|
105
|
+
/**
|
|
106
|
+
* Update resize operation
|
|
107
|
+
* Returns { dx, dy } deltas
|
|
108
|
+
*/
|
|
109
|
+
updateResize(mouseX: number, mouseY: number): {
|
|
110
|
+
dx: number;
|
|
111
|
+
dy: number;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Adjust the resize start position to account for snap corrections
|
|
115
|
+
* This prevents dx/dy from accumulating when a snap is locked
|
|
116
|
+
*/
|
|
117
|
+
adjustResizeStart(deltaX: number, deltaY: number): void;
|
|
118
|
+
/**
|
|
119
|
+
* Get resize context for ResizeHandler
|
|
120
|
+
*/
|
|
121
|
+
getResizeContext(): {
|
|
122
|
+
element: BaseElement;
|
|
123
|
+
handle: HandleInfo;
|
|
124
|
+
startData: TransformStartData;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Update the element in resize context (to preserve state between frames)
|
|
128
|
+
* This is critical for ImageElement crop mode where _lastValidCropState needs to persist
|
|
129
|
+
*/
|
|
130
|
+
updateResizeElement(element: BaseElement): void;
|
|
131
|
+
/**
|
|
132
|
+
* Reset resize start data to current element state (for unfreezing)
|
|
133
|
+
* This updates startData to use the current element dimensions, preventing jumps
|
|
134
|
+
*/
|
|
135
|
+
resetResizeStartData(element: BaseElement, mouseX: number, mouseY: number): void;
|
|
136
|
+
/**
|
|
137
|
+
* Start rotation operation
|
|
138
|
+
*/
|
|
139
|
+
startRotate(element: BaseElement, mouseX: number, mouseY: number, startAngle: number, currentRotation: number): void;
|
|
140
|
+
/**
|
|
141
|
+
* Update rotation operation
|
|
142
|
+
* Returns updated rotation angle in degrees
|
|
143
|
+
*/
|
|
144
|
+
updateRotate(mouseX: number, mouseY: number, centerX: number, centerY: number): number;
|
|
145
|
+
/**
|
|
146
|
+
* Get rotation context
|
|
147
|
+
*/
|
|
148
|
+
getRotationContext(): {
|
|
149
|
+
startAngle: number;
|
|
150
|
+
currentRotation: number;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Start a two-finger pinch gesture on `element`. Captures the
|
|
154
|
+
* gesture's start centroid / distance / angle and the element's
|
|
155
|
+
* full transform snapshot — `updatePinch` then derives the
|
|
156
|
+
* gesture's scale + rotation delta against this snapshot every
|
|
157
|
+
* frame. PinchHandler consumes both via `getPinchContext()` to
|
|
158
|
+
* produce the next element.
|
|
159
|
+
*/
|
|
160
|
+
startPinch(element: BaseElement, p1: Point, p2: Point): void;
|
|
161
|
+
/**
|
|
162
|
+
* Update pinch gesture for the latest two-pointer positions.
|
|
163
|
+
* Returns the raw gesture state (scale ratio, rotation delta,
|
|
164
|
+
* centroid positions). The caller (PinchHandler) is responsible
|
|
165
|
+
* for applying this to the element — keeping the math out of the
|
|
166
|
+
* state machine mirrors how `updateResize` returns `{dx, dy}` and
|
|
167
|
+
* lets `ResizeHandler` do the geometry.
|
|
168
|
+
*
|
|
169
|
+
* Scale is clamped to a small floor so degenerate single-finger
|
|
170
|
+
* coalesces (e.g. fingers landing on the same pixel for one
|
|
171
|
+
* frame) don't produce zero / NaN dimensions.
|
|
172
|
+
*/
|
|
173
|
+
updatePinch(p1: Point, p2: Point): PinchGesture;
|
|
174
|
+
/**
|
|
175
|
+
* Get the element snapshot + pinch start data (used by
|
|
176
|
+
* PinchHandler.calculatePinch). Mirrors `getResizeContext`.
|
|
177
|
+
*/
|
|
178
|
+
getPinchContext(): {
|
|
179
|
+
element: BaseElement;
|
|
180
|
+
startData: TransformStartData;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* End current interaction
|
|
184
|
+
*/
|
|
185
|
+
end(): void;
|
|
186
|
+
/**
|
|
187
|
+
* Cancel current interaction (no commit)
|
|
188
|
+
*/
|
|
189
|
+
cancel(): void;
|
|
190
|
+
/**
|
|
191
|
+
* Get active handle (for resize mode)
|
|
192
|
+
*/
|
|
193
|
+
getActiveHandle(): HandleInfo | null;
|
|
194
|
+
/**
|
|
195
|
+
* Get mode ('drag', 'resize', 'rotate', or null)
|
|
196
|
+
*/
|
|
197
|
+
getMode(): InteractionMode | null;
|
|
198
|
+
}
|
|
199
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BaseElement } from './BaseElement.js';
|
|
2
|
+
import { PathTransformData, PathElementConfig, ResizeAnchor, BoundingBox, Point, TransformStartData } from '../types/index.js';
|
|
3
|
+
export declare class PathElement extends BaseElement {
|
|
4
|
+
transformType: 'path';
|
|
5
|
+
transformData: PathTransformData;
|
|
6
|
+
constructor(config?: Partial<PathElementConfig>);
|
|
7
|
+
/**
|
|
8
|
+
* Get bounding box in world coordinates
|
|
9
|
+
* Returns the unrotated dimensions - rotation is handled by the renderer
|
|
10
|
+
* For paths, calculates actual bounds from path points
|
|
11
|
+
* The bounding box is centered around the element position (this.x, this.y)
|
|
12
|
+
*/
|
|
13
|
+
getBoundingBox(): BoundingBox;
|
|
14
|
+
/**
|
|
15
|
+
* Get visual bounding box (same as regular bounding box for paths)
|
|
16
|
+
* Used for selection display - wraps tightly around actual path
|
|
17
|
+
*/
|
|
18
|
+
getVisualBoundingBox(): BoundingBox;
|
|
19
|
+
/**
|
|
20
|
+
* Get rotation anchor point (center of the path's bounding box)
|
|
21
|
+
*/
|
|
22
|
+
getRotationAnchor(): Point;
|
|
23
|
+
/**
|
|
24
|
+
* Calculate a point on a cubic Bezier curve
|
|
25
|
+
* @param p0 Start point
|
|
26
|
+
* @param p1 First control point
|
|
27
|
+
* @param p2 Second control point
|
|
28
|
+
* @param p3 End point
|
|
29
|
+
* @param t Parameter from 0 to 1
|
|
30
|
+
*/
|
|
31
|
+
private bezierPoint;
|
|
32
|
+
/**
|
|
33
|
+
* Calculate bounding box from path points
|
|
34
|
+
* Returns bbox in local coordinates (relative to element position)
|
|
35
|
+
*/
|
|
36
|
+
private calculatePathBounds;
|
|
37
|
+
/**
|
|
38
|
+
* Update cached bounding box dimensions
|
|
39
|
+
*/
|
|
40
|
+
updateBounds(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Render the path
|
|
43
|
+
*/
|
|
44
|
+
render(ctx: CanvasRenderingContext2D, _isSelected?: boolean, _isHovered?: boolean): void;
|
|
45
|
+
/**
|
|
46
|
+
* Render the path using Canvas API bezier curves
|
|
47
|
+
*/
|
|
48
|
+
private renderPath;
|
|
49
|
+
/**
|
|
50
|
+
* Handle resize - scale all points relative to center
|
|
51
|
+
*/
|
|
52
|
+
resize(anchor: ResizeAnchor, newWidth: number, newHeight: number, startData: TransformStartData): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Get the opposite anchor (the one that should stay fixed during resize)
|
|
55
|
+
*/
|
|
56
|
+
private getOppositeAnchor;
|
|
57
|
+
/**
|
|
58
|
+
* Get the position of the fixed corner (opposite of dragged anchor)
|
|
59
|
+
*/
|
|
60
|
+
private getFixedCorner;
|
|
61
|
+
/**
|
|
62
|
+
* Get the offset of a corner from the center
|
|
63
|
+
*/
|
|
64
|
+
private getCornerOffset;
|
|
65
|
+
/**
|
|
66
|
+
* Get enabled anchors - all 8 anchors for free resize
|
|
67
|
+
*/
|
|
68
|
+
getEnabledAnchors(): ResizeAnchor[];
|
|
69
|
+
/**
|
|
70
|
+
* Clone this element
|
|
71
|
+
*/
|
|
72
|
+
clone(): PathElement;
|
|
73
|
+
/**
|
|
74
|
+
* Serialize to JSON
|
|
75
|
+
*/
|
|
76
|
+
toJSON(): PathElementConfig & {
|
|
77
|
+
id: string;
|
|
78
|
+
type: 'path';
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
rotation: number;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export default PathElement;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { PathPoint, Point } from '../types/index.js';
|
|
2
|
+
import { PathElement } from './PathElement.js';
|
|
3
|
+
export interface PenToolState {
|
|
4
|
+
active: boolean;
|
|
5
|
+
pathElement: PathElement | null;
|
|
6
|
+
points: PathPoint[];
|
|
7
|
+
currentPoint: PathPoint | null;
|
|
8
|
+
isDraggingHandle: boolean;
|
|
9
|
+
previewPoint: Point | null;
|
|
10
|
+
isClosing: boolean;
|
|
11
|
+
closingClickPos: Point | null;
|
|
12
|
+
}
|
|
13
|
+
export declare class PenToolManager {
|
|
14
|
+
private state;
|
|
15
|
+
/**
|
|
16
|
+
* Start pen tool mode with a new path element
|
|
17
|
+
*/
|
|
18
|
+
startPath(pathElement: PathElement): void;
|
|
19
|
+
/**
|
|
20
|
+
* Edit an existing path element
|
|
21
|
+
* Loads the existing points and enters edit mode
|
|
22
|
+
*/
|
|
23
|
+
editPath(pathElement: PathElement): void;
|
|
24
|
+
/**
|
|
25
|
+
* Check if pen tool is active
|
|
26
|
+
*/
|
|
27
|
+
isActive(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Get current state
|
|
30
|
+
*/
|
|
31
|
+
getState(): PenToolState;
|
|
32
|
+
/**
|
|
33
|
+
* Update preview point (for cursor following)
|
|
34
|
+
*/
|
|
35
|
+
setPreviewPoint(x: number, y: number): void;
|
|
36
|
+
/**
|
|
37
|
+
* Clear preview point
|
|
38
|
+
*/
|
|
39
|
+
clearPreviewPoint(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Add a new anchor point at the given position (relative to path element)
|
|
42
|
+
* Returns the created point
|
|
43
|
+
*/
|
|
44
|
+
addPoint(x: number, y: number): PathPoint;
|
|
45
|
+
/**
|
|
46
|
+
* Start dragging handle for the current point
|
|
47
|
+
*/
|
|
48
|
+
startDraggingHandle(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Update handle position for current point (relative to point position)
|
|
51
|
+
*/
|
|
52
|
+
updateHandle(handleX: number, handleY: number): void;
|
|
53
|
+
/**
|
|
54
|
+
* Finish dragging handle
|
|
55
|
+
* If closing the path, this will complete the closing operation
|
|
56
|
+
*/
|
|
57
|
+
finishDraggingHandle(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Check if we can close the path (clicking near first point)
|
|
60
|
+
*/
|
|
61
|
+
canClosePath(x: number, y: number, threshold?: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Start closing the path (allows handle dragging for the closing point)
|
|
64
|
+
* Records where the user clicked so we can calculate handle offsets correctly
|
|
65
|
+
*/
|
|
66
|
+
startClosing(clickX: number, clickY: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Check if currently in closing mode
|
|
69
|
+
*/
|
|
70
|
+
isClosingPath(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Recenter the path element to match where the path was actually drawn
|
|
73
|
+
* Adjusts element position and converts points to be relative to the actual center
|
|
74
|
+
*/
|
|
75
|
+
private recenterPath;
|
|
76
|
+
/**
|
|
77
|
+
* Close the path (connect last point to first)
|
|
78
|
+
*/
|
|
79
|
+
closePath(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Finish the path without closing (leave open)
|
|
82
|
+
*/
|
|
83
|
+
finishPath(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Delete the last added point (undo last point)
|
|
86
|
+
*/
|
|
87
|
+
deleteLastPoint(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Cancel path creation entirely
|
|
90
|
+
*/
|
|
91
|
+
cancelPath(): PathElement | null;
|
|
92
|
+
/**
|
|
93
|
+
* End path creation mode
|
|
94
|
+
*/
|
|
95
|
+
private endPath;
|
|
96
|
+
/**
|
|
97
|
+
* Get points for rendering preview
|
|
98
|
+
*/
|
|
99
|
+
getPoints(): PathPoint[];
|
|
100
|
+
/**
|
|
101
|
+
* Get current point being edited
|
|
102
|
+
*/
|
|
103
|
+
getCurrentPoint(): PathPoint | null;
|
|
104
|
+
/**
|
|
105
|
+
* Check if currently dragging a handle
|
|
106
|
+
*/
|
|
107
|
+
isDraggingHandle(): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Render pen tool preview on canvas
|
|
110
|
+
*/
|
|
111
|
+
renderPreview(ctx: CanvasRenderingContext2D, pathElement: PathElement): void;
|
|
112
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseElement } from './BaseElement.js';
|
|
2
|
+
import { Point, TransformStartData } from '../types/index.js';
|
|
3
|
+
export interface PinchInputs {
|
|
4
|
+
/** Cloned element to mutate — typically `stateMachine.context.element`. */
|
|
5
|
+
element: BaseElement;
|
|
6
|
+
/** Start snapshot of the element's transform (from
|
|
7
|
+
* `BaseElement.getTransformStartData`). Carries the start position,
|
|
8
|
+
* rotation, dimensions, and stroke width that the math reads. */
|
|
9
|
+
startData: TransformStartData;
|
|
10
|
+
/** Distance ratio (current / start). 1 = no scale change. */
|
|
11
|
+
scale: number;
|
|
12
|
+
/** Angle delta in radians (current - start). 0 = no rotate change. */
|
|
13
|
+
rotationDelta: number;
|
|
14
|
+
/** Gesture centroid at gesture start, in world coords. */
|
|
15
|
+
startCentroid: Point;
|
|
16
|
+
/** Gesture centroid right now, in world coords. */
|
|
17
|
+
currentCentroid: Point;
|
|
18
|
+
/**
|
|
19
|
+
* Optional snap hook for cardinal-angle rotation snapping. Same
|
|
20
|
+
* shape as `InteractionStateMachine`'s rotation snap callback —
|
|
21
|
+
* returns possibly-adjusted rotation in degrees.
|
|
22
|
+
*/
|
|
23
|
+
snapRotation?: (rotation: number, element: BaseElement) => number;
|
|
24
|
+
}
|
|
25
|
+
export declare class PinchHandler {
|
|
26
|
+
/**
|
|
27
|
+
* Apply the pinch gesture to `element` in place and return it. The
|
|
28
|
+
* element is expected to already be a clone (the state machine
|
|
29
|
+
* clones on `startPinch`) — this method does not clone again.
|
|
30
|
+
*/
|
|
31
|
+
static calculatePinch({ element, startData, scale, rotationDelta, startCentroid, currentCentroid, snapRotation, }: PinchInputs): BaseElement;
|
|
32
|
+
}
|