@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,31 @@
|
|
|
1
|
+
import { EditorElement } from '../contexts/EditorContext.js';
|
|
2
|
+
export interface UseLayerPreviewOptions {
|
|
3
|
+
/** The element to generate a preview for */
|
|
4
|
+
element: EditorElement;
|
|
5
|
+
/** Preview size in pixels (width and height). Default: 148 */
|
|
6
|
+
size?: number;
|
|
7
|
+
/** Background color for the preview. Default: 'transparent' */
|
|
8
|
+
backgroundColor?: string;
|
|
9
|
+
/** Whether preview generation is enabled. Default: true */
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface UseLayerPreviewReturn {
|
|
13
|
+
/** Data URL of the preview image, or null if not yet generated */
|
|
14
|
+
previewUrl: string | null;
|
|
15
|
+
/** Whether the preview is currently being generated */
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Hook for generating element preview thumbnails.
|
|
20
|
+
*
|
|
21
|
+
* Handles image elements by waiting for the image to load before
|
|
22
|
+
* generating the preview. For text, shape, path, and group elements,
|
|
23
|
+
* the preview is generated synchronously.
|
|
24
|
+
*
|
|
25
|
+
* Automatically regenerates when visual properties change (position,
|
|
26
|
+
* rotation, transform data, text content, image URL, etc.).
|
|
27
|
+
*
|
|
28
|
+
* Debounces regeneration with a 50ms delay to avoid excessive
|
|
29
|
+
* canvas operations during rapid property changes.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useLayerPreview(options: UseLayerPreviewOptions): UseLayerPreviewReturn;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useLayerSelection - Hook for layer selection logic
|
|
3
|
+
*
|
|
4
|
+
* Extracts the selection logic (shift-click multi-select, single-click,
|
|
5
|
+
* deselection) from LayersPanel.tsx into a reusable hook.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* function LayersList({ elements }) {
|
|
10
|
+
* const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
11
|
+
* const [multiSelection, setMultiSelection] = useState<string[]>([]);
|
|
12
|
+
*
|
|
13
|
+
* const { isSelected, handleClick } = useLayerSelection({
|
|
14
|
+
* selectedId,
|
|
15
|
+
* multiSelection,
|
|
16
|
+
* onSelectionChange: setSelectedId,
|
|
17
|
+
* onMultiSelectionChange: setMultiSelection,
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* return elements.map(el => (
|
|
21
|
+
* <div
|
|
22
|
+
* key={el.id}
|
|
23
|
+
* className={isSelected(el.id) ? 'selected' : ''}
|
|
24
|
+
* onClick={(e) => handleClick(e, el.id)}
|
|
25
|
+
* />
|
|
26
|
+
* ));
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export interface UseLayerSelectionOptions {
|
|
31
|
+
/** Currently selected single element ID, or null */
|
|
32
|
+
selectedId: string | null;
|
|
33
|
+
/** Array of multi-selected element IDs */
|
|
34
|
+
multiSelection: string[];
|
|
35
|
+
/** Callback for single selection changes */
|
|
36
|
+
onSelectionChange: (id: string | null) => void;
|
|
37
|
+
/** Callback for multi-selection changes */
|
|
38
|
+
onMultiSelectionChange: (ids: string[]) => void;
|
|
39
|
+
}
|
|
40
|
+
export interface UseLayerSelectionReturn {
|
|
41
|
+
/**
|
|
42
|
+
* Check if an element is selected (either single or multi-selected).
|
|
43
|
+
* Does not account for activeChildElement priority -- callers handling
|
|
44
|
+
* group children should check that separately.
|
|
45
|
+
*/
|
|
46
|
+
isSelected: (id: string) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Handle a click on a layer element.
|
|
49
|
+
* - Normal click: selects only this element, clears multi-selection
|
|
50
|
+
* - Shift+click: toggles the element in/out of multi-selection
|
|
51
|
+
*/
|
|
52
|
+
handleClick: (e: React.MouseEvent | React.KeyboardEvent, elementId: string) => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Hook for managing layer selection state.
|
|
56
|
+
*
|
|
57
|
+
* Implements the following selection behaviors:
|
|
58
|
+
*
|
|
59
|
+
* **Normal click:**
|
|
60
|
+
* - Selects only the clicked element
|
|
61
|
+
* - Clears any multi-selection
|
|
62
|
+
*
|
|
63
|
+
* **Shift+click with existing multi-selection:**
|
|
64
|
+
* - If element is in multi-selection: removes it
|
|
65
|
+
* - If only 1 remains: converts back to single selection
|
|
66
|
+
* - If 0 remain: clears selection
|
|
67
|
+
* - If element is not in multi-selection: adds it
|
|
68
|
+
*
|
|
69
|
+
* **Shift+click with single selection:**
|
|
70
|
+
* - If clicking the already-selected element: no-op
|
|
71
|
+
* - If clicking a different element: starts multi-selection with both
|
|
72
|
+
*
|
|
73
|
+
* **Shift+click with no selection:**
|
|
74
|
+
* - Selects the clicked element as a single selection
|
|
75
|
+
*/
|
|
76
|
+
export declare function useLayerSelection(options: UseLayerSelectionOptions): UseLayerSelectionReturn;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { GroupElement } from '../core/GroupElement.js';
|
|
2
|
+
import { EditorElement } from '../contexts/EditorContext.js';
|
|
3
|
+
import { TransformType } from '../types/index.js';
|
|
4
|
+
import { ArtboardManager } from '../core/ArtboardManager.js';
|
|
5
|
+
export interface LayerInfo {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: TransformType;
|
|
9
|
+
visible: boolean;
|
|
10
|
+
locked: boolean;
|
|
11
|
+
isSelected: boolean;
|
|
12
|
+
isGroup: boolean;
|
|
13
|
+
depth: number;
|
|
14
|
+
parentId: string | null;
|
|
15
|
+
children?: LayerInfo[];
|
|
16
|
+
previewUrl: string | null;
|
|
17
|
+
refreshPreview: () => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface UseLayersOptions {
|
|
20
|
+
artboardId?: string | null;
|
|
21
|
+
includeHidden?: boolean;
|
|
22
|
+
previewSize?: number;
|
|
23
|
+
previewBackgroundColor?: string;
|
|
24
|
+
autoRefreshPreviews?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface UseLayersReturn {
|
|
27
|
+
layers: LayerInfo[];
|
|
28
|
+
flatLayers: LayerInfo[];
|
|
29
|
+
selectedLayers: LayerInfo[];
|
|
30
|
+
selectLayer: (id: string, addToSelection?: boolean) => void;
|
|
31
|
+
selectMultipleLayers: (ids: string[]) => void;
|
|
32
|
+
clearSelection: () => void;
|
|
33
|
+
toggleVisibility: (id: string) => void;
|
|
34
|
+
toggleLock: (id: string) => void;
|
|
35
|
+
renameLayer: (id: string, name: string) => void;
|
|
36
|
+
deleteLayer: (id: string) => void;
|
|
37
|
+
duplicateLayer: (id: string) => void;
|
|
38
|
+
reorderLayers: (fromIndex: number, toIndex: number) => void;
|
|
39
|
+
reorderById: (draggedId: string, targetId: string, position: 'before' | 'after') => void;
|
|
40
|
+
reorderWithinGroup: (draggedId: string, targetId: string, position: 'before' | 'after', groupId: string) => void;
|
|
41
|
+
moveLayerForward: (id: string) => void;
|
|
42
|
+
moveLayerBackward: (id: string) => void;
|
|
43
|
+
groupLayers: (ids: string[]) => void;
|
|
44
|
+
ungroupLayer: (id: string) => void;
|
|
45
|
+
addToGroup: (elementId: string, groupId: string) => void;
|
|
46
|
+
removeFromGroup: (elementId: string, targetId?: string, position?: 'before' | 'after') => void;
|
|
47
|
+
createEmptyGroup: () => void;
|
|
48
|
+
findElementById: (id: string) => EditorElement | null;
|
|
49
|
+
findParentGroup: (id: string) => GroupElement | null;
|
|
50
|
+
generateAllPreviews: (size?: number) => Promise<void>;
|
|
51
|
+
clearPreviewCache: () => void;
|
|
52
|
+
artboardId: string | null;
|
|
53
|
+
artboardManager: ArtboardManager;
|
|
54
|
+
layerCount: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Hook for accessing layer data and operations
|
|
58
|
+
* Must be used within EditorProvider
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* function CustomLayersPanel() {
|
|
63
|
+
* const { layers, selectLayer, toggleVisibility, deleteLayer } = useLayers({
|
|
64
|
+
* previewSize: 80,
|
|
65
|
+
* autoRefreshPreviews: true
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* return (
|
|
69
|
+
* <div className="layers-panel">
|
|
70
|
+
* {layers.map(layer => (
|
|
71
|
+
* <div
|
|
72
|
+
* key={layer.id}
|
|
73
|
+
* className={layer.isSelected ? 'selected' : ''}
|
|
74
|
+
* style={{ paddingLeft: layer.depth * 20 }}
|
|
75
|
+
* >
|
|
76
|
+
* {layer.previewUrl && (
|
|
77
|
+
* <img src={layer.previewUrl} alt={layer.name} width={40} />
|
|
78
|
+
* )}
|
|
79
|
+
* <span onClick={() => selectLayer(layer.id)}>{layer.name}</span>
|
|
80
|
+
* <button onClick={() => toggleVisibility(layer.id)}>
|
|
81
|
+
* {layer.visible ? '👁' : '🚫'}
|
|
82
|
+
* </button>
|
|
83
|
+
* <button onClick={() => deleteLayer(layer.id)}>🗑</button>
|
|
84
|
+
* </div>
|
|
85
|
+
* ))}
|
|
86
|
+
* </div>
|
|
87
|
+
* );
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function useLayers(options?: UseLayersOptions): UseLayersReturn;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePerformance - Hook for performance monitoring
|
|
3
|
+
* Provides metrics for tracking editor performance
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* function PerformanceMonitor() {
|
|
8
|
+
* const { metrics, startProfiling } = usePerformance();
|
|
9
|
+
*
|
|
10
|
+
* useEffect(() => {
|
|
11
|
+
* startProfiling();
|
|
12
|
+
* }, []);
|
|
13
|
+
*
|
|
14
|
+
* if (metrics.fps < 30) {
|
|
15
|
+
* console.warn('Low FPS:', metrics.fps);
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* return (
|
|
19
|
+
* <div>
|
|
20
|
+
* <p>FPS: {Math.round(metrics.fps)}</p>
|
|
21
|
+
* <p>Render Time: {metrics.avgRenderTime.toFixed(2)}ms</p>
|
|
22
|
+
* <p>Elements: {metrics.elementCount}</p>
|
|
23
|
+
* </div>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export interface PerformanceMetrics {
|
|
29
|
+
fps: number;
|
|
30
|
+
avgRenderTime: number;
|
|
31
|
+
peakRenderTime: number;
|
|
32
|
+
memoryUsage: number;
|
|
33
|
+
elementCount: number;
|
|
34
|
+
exportCount: number;
|
|
35
|
+
avgExportTime: number;
|
|
36
|
+
}
|
|
37
|
+
export interface UsePerformanceReturn {
|
|
38
|
+
metrics: PerformanceMetrics;
|
|
39
|
+
startProfiling: () => void;
|
|
40
|
+
stopProfiling: () => void;
|
|
41
|
+
clearMetrics: () => void;
|
|
42
|
+
getReport: () => string;
|
|
43
|
+
isProfiling: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Hook for performance monitoring
|
|
47
|
+
*/
|
|
48
|
+
export declare function usePerformance(): UsePerformanceReturn;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CanvasDocument } from '../utils/ExportManager.js';
|
|
2
|
+
import { AnyElementConfig } from '../types/index.js';
|
|
3
|
+
export interface ProjectTemplate {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
artboards: Array<{
|
|
7
|
+
name: string;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
backgroundColor: string;
|
|
11
|
+
elements?: AnyElementConfig[];
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export interface ProjectMetadata {
|
|
15
|
+
version: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
artboardCount: number;
|
|
18
|
+
elementCount: number;
|
|
19
|
+
}
|
|
20
|
+
export interface UseProjectLoaderReturn {
|
|
21
|
+
loadFromJSON: (json: string | CanvasDocument) => Promise<void>;
|
|
22
|
+
loadFromFile: (file: File) => Promise<void>;
|
|
23
|
+
loadTemplate: (template: ProjectTemplate) => Promise<void>;
|
|
24
|
+
isLoading: boolean;
|
|
25
|
+
loadError: Error | null;
|
|
26
|
+
currentProject: CanvasDocument | null;
|
|
27
|
+
projectMetadata: ProjectMetadata | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Hook for loading saved projects
|
|
31
|
+
* Must be used within EditorProvider
|
|
32
|
+
*
|
|
33
|
+
* @example Load from API
|
|
34
|
+
* ```tsx
|
|
35
|
+
* function ProductCustomizer({ productId }: { productId: string }) {
|
|
36
|
+
* const { loadFromJSON, isLoading } = useProjectLoader();
|
|
37
|
+
*
|
|
38
|
+
* useEffect(() => {
|
|
39
|
+
* fetch(`/api/designs/${productId}`)
|
|
40
|
+
* .then(res => res.json())
|
|
41
|
+
* .then(design => loadFromJSON(design))
|
|
42
|
+
* .catch(console.error);
|
|
43
|
+
* }, [productId]);
|
|
44
|
+
*
|
|
45
|
+
* if (isLoading) return <div>Loading design...</div>;
|
|
46
|
+
*
|
|
47
|
+
* return <Canvas />;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @example Load from template
|
|
52
|
+
* ```tsx
|
|
53
|
+
* function TemplateGallery() {
|
|
54
|
+
* const { loadTemplate } = useProjectLoader();
|
|
55
|
+
*
|
|
56
|
+
* const handleSelectTemplate = (template: ProjectTemplate) => {
|
|
57
|
+
* loadTemplate(template);
|
|
58
|
+
* };
|
|
59
|
+
*
|
|
60
|
+
* return <div>Template gallery...</div>;
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function useProjectLoader(): UseProjectLoaderReturn;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EditorElement } from '../contexts/EditorContext.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the currently selected element, or null if nothing is selected.
|
|
4
|
+
*
|
|
5
|
+
* This is a convenience wrapper around `useEditor()` that only extracts
|
|
6
|
+
* selection state, keeping consumer components focused on what they need.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* function PropertiesPanel() {
|
|
11
|
+
* const selected = useSelectedElement();
|
|
12
|
+
* if (!selected) return <p>Nothing selected</p>;
|
|
13
|
+
* return <p>Selected: {selected.id}</p>;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function useSelectedElement(): EditorElement | null;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EditorElement } from '../contexts/EditorContext.js';
|
|
2
|
+
/** Result returned by {@link useTextBinding}. */
|
|
3
|
+
export interface TextBindingResult {
|
|
4
|
+
/** Current plain text content (from first bound element). Empty string if disconnected. */
|
|
5
|
+
text: string;
|
|
6
|
+
/** Update text on all bound elements. No-op if disconnected. */
|
|
7
|
+
setText: (text: string) => void;
|
|
8
|
+
/** The first bound element, or null if no matching text element exists. */
|
|
9
|
+
element: EditorElement | null;
|
|
10
|
+
/** All bound text elements (empty array if disconnected). */
|
|
11
|
+
elements: readonly EditorElement[];
|
|
12
|
+
/** Whether at least one matching text element exists. */
|
|
13
|
+
isConnected: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Bind an HTML input to canvas text elements by their `name` property.
|
|
17
|
+
*
|
|
18
|
+
* Multiple elements can share the same name — `setText` updates all of them.
|
|
19
|
+
* Text is read from the first matching element (render order).
|
|
20
|
+
*
|
|
21
|
+
* Must be used within an `EditorProvider`.
|
|
22
|
+
*
|
|
23
|
+
* @param name - The element name to bind to.
|
|
24
|
+
* @returns Text value, setter, element references, and connection status.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useTextBinding(name: string): TextBindingResult;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { TransformType, TextAlign, CharacterStyle } from '../types/index.js';
|
|
2
|
+
import { CanvasEditorHandle } from '../components/CanvasEditor.js';
|
|
3
|
+
export interface UseTextToolbarOptions {
|
|
4
|
+
canvasEditorRef?: React.RefObject<CanvasEditorHandle | null>;
|
|
5
|
+
}
|
|
6
|
+
export interface UseTextToolbarReturn {
|
|
7
|
+
fontSize: number;
|
|
8
|
+
fontColor: string;
|
|
9
|
+
fontFamily: string;
|
|
10
|
+
textAlign: TextAlign;
|
|
11
|
+
bold: boolean;
|
|
12
|
+
italic: boolean;
|
|
13
|
+
underline: boolean;
|
|
14
|
+
letterCase: string;
|
|
15
|
+
handleFontSizeChange: (size: number) => void;
|
|
16
|
+
handleFontSizeIncrement: (delta: number) => void;
|
|
17
|
+
handleFontFamilyChange: (family: string) => void;
|
|
18
|
+
handleFontColorChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
19
|
+
handleBoldToggle: () => void;
|
|
20
|
+
handleItalicToggle: () => void;
|
|
21
|
+
handleUnderlineToggle: () => void;
|
|
22
|
+
handleLetterCaseToggle: () => void;
|
|
23
|
+
isLetterCaseActive: () => boolean;
|
|
24
|
+
handleTextAlignToggle: () => void;
|
|
25
|
+
getEffectiveStyle: () => CharacterStyle;
|
|
26
|
+
handleTransformTypeChange: (type: TransformType) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hook for text element formatting state and handlers.
|
|
30
|
+
*
|
|
31
|
+
* Extracts all text-specific toolbar logic (font size, color, family,
|
|
32
|
+
* bold/italic/underline, letter case, text align, transform type) so it
|
|
33
|
+
* can be reused across different toolbar layouts.
|
|
34
|
+
*
|
|
35
|
+
* Uses `useEditor()` internally. Pass a `canvasEditorRef` to enable
|
|
36
|
+
* character-level rich text formatting during text editing mode.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Configuration options
|
|
39
|
+
* @returns Text toolbar state and handler functions
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* function MyTextToolbar() {
|
|
44
|
+
* const toolbar = useTextToolbar({ canvasEditorRef });
|
|
45
|
+
*
|
|
46
|
+
* return (
|
|
47
|
+
* <div>
|
|
48
|
+
* <button onClick={toolbar.handleBoldToggle}>
|
|
49
|
+
* Bold: {toolbar.bold ? 'ON' : 'OFF'}
|
|
50
|
+
* </button>
|
|
51
|
+
* <input
|
|
52
|
+
* type="number"
|
|
53
|
+
* value={toolbar.fontSize}
|
|
54
|
+
* onChange={(e) => toolbar.handleFontSizeChange(Number(e.target.value))}
|
|
55
|
+
* />
|
|
56
|
+
* </div>
|
|
57
|
+
* );
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function useTextToolbar(options?: UseTextToolbarOptions): UseTextToolbarReturn;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { PanOffset } from '../contexts/ViewportContext.js';
|
|
3
|
+
/**
|
|
4
|
+
* Return type for {@link useViewport}.
|
|
5
|
+
*/
|
|
6
|
+
export interface UseViewportReturn {
|
|
7
|
+
/** Current zoom level (1.0 = 100%) */
|
|
8
|
+
zoom: number;
|
|
9
|
+
/** Current pan offset in world coordinates */
|
|
10
|
+
panOffset: PanOffset;
|
|
11
|
+
/** Increment zoom by one step */
|
|
12
|
+
zoomIn: () => void;
|
|
13
|
+
/** Decrement zoom by one step */
|
|
14
|
+
zoomOut: () => void;
|
|
15
|
+
/** Zoom to fit the active artboard in the viewport */
|
|
16
|
+
zoomToFit: () => void;
|
|
17
|
+
/** Reset zoom to 100% and pan offset to origin */
|
|
18
|
+
resetView: () => void;
|
|
19
|
+
/** Set zoom to an exact value */
|
|
20
|
+
setZoom: React.Dispatch<React.SetStateAction<number>>;
|
|
21
|
+
/** Set pan offset to an exact value */
|
|
22
|
+
setPanOffset: React.Dispatch<React.SetStateAction<PanOffset>>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns viewport state (zoom, pan) and control functions.
|
|
26
|
+
*
|
|
27
|
+
* This hook now reads directly from ViewportContext (instead of the full
|
|
28
|
+
* EditorContext), so components using it will only re-render when viewport
|
|
29
|
+
* state changes -- not when elements, selection, or other state changes.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function ZoomBar() {
|
|
34
|
+
* const { zoom, zoomIn, zoomOut, zoomToFit } = useViewport();
|
|
35
|
+
* return (
|
|
36
|
+
* <div>
|
|
37
|
+
* <button onClick={zoomOut}>-</button>
|
|
38
|
+
* <span>{Math.round(zoom * 100)}%</span>
|
|
39
|
+
* <button onClick={zoomIn}>+</button>
|
|
40
|
+
* <button onClick={zoomToFit}>Fit</button>
|
|
41
|
+
* </div>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function useViewport(): UseViewportReturn;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon Registry - Registers only the icons actually used in the canvas package
|
|
3
|
+
*
|
|
4
|
+
* This ensures icons work when the canvas package is bundled and used in
|
|
5
|
+
* consuming applications (like Next.js) where CDN icon loading may fail.
|
|
6
|
+
*
|
|
7
|
+
* Icons are auto-generated by scripts/generate-icons.ts which scans the source
|
|
8
|
+
* files and extracts only the SVG data for icons that are actually used.
|
|
9
|
+
* This dramatically reduces bundle size compared to bundling entire icon sets.
|
|
10
|
+
*
|
|
11
|
+
* To regenerate after adding new icons:
|
|
12
|
+
* pnpm generate:icons
|
|
13
|
+
*
|
|
14
|
+
* @see https://iconify.design/docs/icons/json.html
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Registers all icons used in the canvas package.
|
|
18
|
+
* Call this function once when the application loads.
|
|
19
|
+
*
|
|
20
|
+
* This function registers only the ~100-150 icons actually used,
|
|
21
|
+
* rather than ~20,000+ icons from the full icon sets.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerCanvasIcons(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Ensures icons are registered exactly once.
|
|
26
|
+
* Safe to call multiple times.
|
|
27
|
+
*/
|
|
28
|
+
export declare function ensureIconsRegistered(): void;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const I=require("./compose-Bo108juW.cjs"),U=require("./HybridHistoryManager-BXD93pp8.cjs"),C=require("react/jsx-runtime"),o=require("react"),B=require("./ThemeContext-4mJ_y0Me.cjs"),le=require("./ElementFactory-B7UOaJSD.cjs"),de=require("./CanvasStateV1-D5GzvmnY.cjs"),it=U.createLogger("ErrorBoundary");class ze extends o.Component{constructor(e){super(e),this.resetError=()=>{this.setState({hasError:!1,error:null})},this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,r){if(it.error("Caught error:",e,r),this.props.onError&&this.props.onError(e,r),this.props.onCanvasError){const a={category:"unknown",message:e.message,originalError:e,recoverable:!1};this.props.onCanvasError(a)}}render(){return this.state.hasError&&this.state.error?this.props.renderError?this.props.renderError(this.state.error,this.resetError):this.props.fallback?typeof this.props.fallback=="function"?this.props.fallback(this.state.error,this.resetError):this.props.fallback:C.jsxs("div",{style:{padding:"24px",border:"2px solid var(--danger)",borderRadius:"8px",backgroundColor:"color-mix(in oklch, var(--danger) 10%, var(--background))",color:"var(--danger)",fontFamily:"system-ui, sans-serif"},children:[C.jsx("h2",{style:{margin:"0 0 16px 0",fontSize:"18px",fontWeight:600},children:"Something went wrong"}),C.jsx("pre",{style:{margin:"0 0 16px 0",padding:"12px",backgroundColor:"color-mix(in oklch, var(--danger) 15%, var(--background))",borderRadius:"4px",fontSize:"14px",overflow:"auto",maxHeight:"200px"},children:this.state.error.message}),C.jsx("button",{onClick:this.resetError,style:{padding:"8px 16px",backgroundColor:"var(--danger)",color:"var(--danger-foreground)",border:"none",borderRadius:"4px",fontSize:"14px",fontWeight:500,cursor:"pointer"},children:"Try again"})]}):this.props.children}}const ct=U.createLogger("useAutoExport");function Oe(t){const{config:e,historyManager:r,artboards:a,elements:n,onExport:l,onExportScheduled:s,isCanvasReady:c=!1}=t,d=o.useRef(null),b=o.useRef(!1),S=o.useRef({totalExports:0,skippedExports:0,lastExportTime:null,avgExportInterval:0}),[L,k]=o.useState(S.current),y=o.useRef(l);y.current=l,o.useEffect(()=>{const h=new I.AutoExportManager({...I.DEFAULT_AUTO_EXPORT_CONFIG,...e});return h.onExport(async()=>{try{await y.current(),S.current=h.getStats()}catch(R){ct.error("[useAutoExport] Export failed:",R)}}),d.current=h,()=>{h.destroy()}},[]),o.useEffect(()=>{c&&b.current&&d.current&&(b.current=!1,d.current.forceExport())},[c]),o.useEffect(()=>{d.current&&e&&d.current.updateConfig(e)},[e==null?void 0:e.enabled,e==null?void 0:e.debounceMs,e==null?void 0:e.maxWaitMs]),o.useEffect(()=>{d.current&&s&&d.current.onExportScheduled(s)},[s]),o.useEffect(()=>{if(!r||!d.current)return;const h=r.onCommandExecuted(()=>{if(d.current){if(!c){b.current=!0;return}d.current.scheduleExport()}});return()=>{h()}},[r,c]),o.useEffect(()=>{if(d.current){if(!c){b.current=!0;return}d.current.scheduleExport()}},[n,a,c]),o.useEffect(()=>U.subscribeToImageLoads(R=>{if(!d.current||!c)return;n.some(W=>W.id===R)&&d.current.scheduleExport()}),[n,c]);const T=o.useCallback(h=>{d.current&&d.current.updateConfig(h)},[]),w=o.useCallback(async()=>{d.current&&(await d.current.forceExport(),S.current=d.current.getStats(),k(S.current))},[]),P=o.useCallback(()=>{d.current&&(d.current.resetStats(),S.current=d.current.getStats(),k(S.current))},[]),A=o.useCallback(()=>{d.current&&d.current.resetChangeDetection()},[]);return{stats:L,updateConfig:T,forceExport:w,resetStats:P,resetChangeDetection:A}}const Ye=U.createLogger("useContentReady");function lt(t){var r;const e=new Set;for(const a of t)if("fontFamily"in a&&typeof a.fontFamily=="string"&&a.fontFamily&&e.add(a.fontFamily),"getRichText"in a&&typeof a.getRichText=="function")try{const n=a.getRichText();if(n!=null&&n.spans)for(const l of n.spans)(r=l.style)!=null&&r.fontFamily&&e.add(l.style.fontFamily)}catch{}return Array.from(e)}async function dt(t){if(t.length===0||typeof document>"u"||!document.fonts)return;const e=[];for(const r of t){const a=`16px "${r}"`;e.push(document.fonts.load(a))}await Promise.all(e),document.fonts.ready&&await Promise.race([document.fonts.ready,new Promise(r=>setTimeout(r,250))]),Ye.debug(`Awaited ${e.length} font(s)`)}function ut(){return new Promise(t=>requestAnimationFrame(()=>t()))}function $e(t){const{isCanvasReady:e,elements:r,hasInitialElements:a,initialElementsLoaded:n}=t,[l,s]=o.useState(!1),c=o.useRef(!1);return o.useEffect(()=>{if(l||!e||a&&!n||a&&r.length===0||c.current)return;c.current=!0;let d=!1;return(async()=>{try{const b=lt(r);if(b.length>0&&(await dt(b),d)||(await ut(),d))return;s(!0)}catch(b){Ye.error("Error during content readiness check:",b),d||s(!0)}finally{c.current=!1}})(),()=>{d=!0,c.current=!1}},[e,r,a,n,l]),l}const ft={"far-top":"t",top:"t",center:"c",bottom:"b","far-bottom":"b","far-left":"l",left:"l",right:"r","far-right":"r",tl:"tl",t:"t",tr:"tr",l:"l",c:"c",r:"r",bl:"bl",b:"b",br:"br"};function mt(t){return t&&ft[t]||"c"}function ht(t,e){const r=e.scaleMode||"cover",a=(r==="contain"?e.marginTop:0)||0,n=(r==="contain"?e.marginRight:0)||0,l=(r==="contain"?e.marginBottom:0)||0,s=(r==="contain"?e.marginLeft:0)||0,c=e.width-s-n,d=e.height-a-l,b=c/t.width,S=d/t.height,L=r==="contain"?Math.min(b,S):Math.max(b,S),k=e.scale||1,y=L*k,T=t.width*y,w=t.height*y,P=e.align||"c";let A=0,h=0;const R=T-c,E=w-d;switch(P){case"tl":A=0,h=0;break;case"t":A=-R/2,h=0;break;case"tr":A=-R,h=0;break;case"l":A=0,h=-E/2;break;case"c":default:A=-R/2,h=-E/2;break;case"r":A=-R,h=-E/2;break;case"bl":A=0,h=-E;break;case"b":A=-R/2,h=-E;break;case"br":A=-R,h=-E;break}A+=s,h+=a;const W=e.offsetX||0,F=e.offsetY||0,Y=R,_=E;return A+=W*Y,h+=F*_,A=Math.round(A),h=Math.round(h),{scale:y,width:Math.round(T),height:Math.round(w),x:A,y:h,debug:{coverScale:L,userScale:k,overflow:{x:R,y:E},alignment:P,appliedOffset:{x:W*Y,y:F*_}}}}const gt={timeout:3e4,retries:1,retryDelay:1e3,validateUrl:!0};function pt(t){try{const e=new URL(t);return["http:","https:","data:","blob:"].includes(e.protocol)}catch{return!1}}async function bt(t,e={}){const r={...gt,...e};if(r.validateUrl&&!pt(t))return{success:!1,error:new Error(`Invalid image URL: ${t}`)};let a;for(let n=0;n<=r.retries;n++)try{return await xt(t,r.timeout)}catch(l){a=l instanceof Error?l:new Error(String(l)),n<r.retries&&await vt(r.retryDelay)}return{success:!1,error:a||new Error("Failed to load image after retries")}}function xt(t,e){return new Promise(r=>{const a=new Image;a.crossOrigin="anonymous";let n=null,l=!1;const s=()=>{n&&(clearTimeout(n),n=null)},c=()=>{if(l)return;l=!0,s();const b=a.naturalWidth||a.width,S=a.naturalHeight||a.height;r({success:!0,element:a,width:b,height:S,aspectRatio:S>0?b/S:1})},d=b=>{l||(l=!0,s(),r({success:!1,error:new Error(b)}))};a.onload=c,a.onerror=()=>{d(`Failed to load image: ${t}`)},n=setTimeout(()=>{d(`Image load timed out after ${e}ms: ${t}`)},e),a.src=t})}async function Et(t,e,r={},a={}){var k,y,T,w,P,A,h;const n=await bt(t,a);if(!n.success||!n.width||!n.height)return{success:!1,error:n.error||new Error("Failed to get image dimensions")};const l={width:e.artboard.width,height:e.artboard.height,scale:e.scale,align:mt(e.alignment),offsetX:e.offsetX,offsetY:e.offsetY,scaleMode:e.scaleMode,marginTop:e.marginTop,marginRight:e.marginRight,marginBottom:e.marginBottom,marginLeft:e.marginLeft},s=ht({width:n.width,height:n.height},l),c=e.artboard.x+s.x,d=e.artboard.y+s.y,b=c+s.width/2,S=d+s.height/2;return{success:!0,element:new U.ImageElement({...r,x:b,y:S,imageUrl:t,imageAspectRatio:n.aspectRatio,preserveDimensions:!0,transformData:{type:"image",width:s.width,height:s.height,cropX:((k=r.transformData)==null?void 0:k.cropX)??0,cropY:((y=r.transformData)==null?void 0:y.cropY)??0,cropWidth:((T=r.transformData)==null?void 0:T.cropWidth)??1,cropHeight:((w=r.transformData)==null?void 0:w.cropHeight)??1,flipHorizontal:((P=r.transformData)==null?void 0:P.flipHorizontal)??!1,flipVertical:((A=r.transformData)==null?void 0:A.flipVertical)??!1,borderRadius:((h=r.transformData)==null?void 0:h.borderRadius)??0}}),placement:{artworkSize:{width:n.width,height:n.height},finalSize:{width:s.width,height:s.height},position:{x:b,y:S},scale:s.scale}}}function vt(t){return new Promise(e=>setTimeout(e,t))}const V=U.createLogger("SnowconeCanvas");function Ee(t,e,r,a){if(a<=0||!isFinite(a))return r;const n=t*r,l=e*r;if(Math.max(n,l)<=a)return r;const c=Math.max(t,e),d=a/c;return Math.min(d,r)}const Xe=o.forwardRef((t,e)=>{const{exportConfig:r,imageConfig:a,layoutConfig:n,kit:l,artboards:s,activeArtboard:c,onArtboardChange:d,initialElements:b,onChange:S,onSelectionChange:L,autoExportInterval:k,onExport:y,onExportScheduled:T,onExportStatus:w,onExportReady:P,onImageLoad:A,onImageError:h,onError:R,onReady:E,className:W,style:F,enableShortcuts:Y,overlay:_}=t,we=k,Z=t.autoExportConfig??(r==null?void 0:r.autoExportConfig),q=t.autoExportFormat??(r==null?void 0:r.format)??"dataUrl",ue=t.autoExportAll??(r==null?void 0:r.exportAll)??!1,X=t.exportScale??(r==null?void 0:r.scale)??2,j=t.maxExportSize??(r==null?void 0:r.maxSize)??4e3,ee=t.exportImageFormat??(r==null?void 0:r.imageFormat)??"png",te=t.exportImageQuality??(r==null?void 0:r.imageQuality)??.92,z=t.initialImage??(a==null?void 0:a.src),ye=t.initialImageAlignment??(a==null?void 0:a.alignment)??"center",Ae=t.initialImageScale??(a==null?void 0:a.scale)??1,Se=t.initialImageScaleMode??(a==null?void 0:a.scaleMode)??"cover",Ke=t.width??(n==null?void 0:n.width)??1200,Ve=t.height??(n==null?void 0:n.height)??1200,Re=t.viewPadding??(n==null?void 0:n.viewPadding)??.9,Ce=t.artboardBorderRadius??(n==null?void 0:n.artboardBorderRadius)??0,Ie=t.fixedMargin??(n==null?void 0:n.fixedMargin),ke=t.maxHeight??(n==null?void 0:n.maxHeight),Me=t.showRotationHandle??(n==null?void 0:n.showRotationHandle)??!0,qe=t.hideCanvas??(n==null?void 0:n.hideCanvas)??!1,Te=t.canvasWrapperClassName??(n==null?void 0:n.canvasWrapperClassName),Fe=t.canvasWrapperStyle??(n==null?void 0:n.canvasWrapperStyle),De=t.canvasCutouts??(n==null?void 0:n.canvasCutouts),fe=t.pieceGuides,Le=t.pieceFocus,Pe=Y??!0,re=o.useMemo(()=>I.resolveKit(l??"pro-studio"),[l]);o.useEffect(()=>{if(U.process$1.env.NODE_ENV==="development"&&re){const i=I.validateKit(re);i.valid||V.warn("Kit validation warnings:",i.errors),i.warnings.length>0&&V.warn("Kit validation warnings:",i.warnings)}},[re]);const ne=o.useRef(R);ne.current=R;const N=o.useCallback(i=>{var u;V.error(`[${i.category}] ${i.message}`,i.originalError),(u=ne.current)==null||u.call(ne,i)},[]);o.useEffect(()=>(le.CanvasRenderer.onRenderError=N,()=>{le.CanvasRenderer.onRenderError===N&&(le.CanvasRenderer.onRenderError=null)}),[N]);const{elements:K,setElements:ae,selectedId:He,artboardManager:M,refreshArtboards:Ge,historyManager:Qe,isCanvasReady:me,setCanvasReady:oe}=B.useEditor(),{createArtboard:Ze,selectArtboard:Je,artboards:H}=I.useArtboards(),{exportArtboard:G,exportAllArtboards:se,exportArtboardAsBlob:Q,exportAllArtboardsAsBlobs:ie}=I.useExport();o.useImperativeHandle(e,()=>({exportArtboards:async(i={})=>{const u=i.format||q,g=i.scale||X,p=i.all??!1;let m=g;if(j>0&&isFinite(j))for(const v of H){const x=Ee(v.width,v.height,g,j);m=Math.min(m,x)}const f={scale:m,format:ee,quality:te};if(p){const v=u==="blob"?await ie(f):await se(f),x={};for(const[D,O]of Object.entries(v)){const $=H.find(J=>J.id===D);$&&(x[$.name]=O)}return x}else{const v=M.getActiveArtboard();if(!v)throw new Error("[SnowconeCanvas] No active artboard found");if(u==="blob"){const x=await Q(v.id,f);return{[v.name]:x}}else{const x=await G(v.id,f);return{[v.name]:x}}}}}),[G,se,Q,ie,q,X,j,ee,te,M,H]),o.useEffect(()=>{P&&P(async()=>{const u=M.getActiveArtboard();if(!u)throw new Error("[SnowconeCanvas] No active artboard found");const g=Ee(u.width,u.height,X,j),p=q==="blob"?await Q(u.id,{scale:g}):await G(u.id,{scale:g});return{[u.name]:p}})},[P,G,Q,M,q,X,j]);const[Be,ce]=o.useState("idle"),[We,he]=o.useState(null),ge=o.useRef(void 0),pe=o.useRef(!1),Ne=o.useRef(!1),[_e,et]=o.useState(!1),tt=o.useRef(0),rt=o.useRef(0),be=o.useRef(!1);o.useEffect(()=>{if(pe.current)return;pe.current=!0;const i=s||[{name:"Design",width:Ke,height:Ve}],u=M.getAllArtboards();if(u.length>0){const g=i[0],p=u[0],m=fe?"transparent":void 0;p.name=g.name,p.width=g.width,p.height=g.height,p.clipShape=g.clipShape,g.backgroundColor?p.backgroundColor=g.backgroundColor:m&&(p.backgroundColor=m);for(let f=1;f<i.length;f++)Ze(i[f].width,i[f].height,{name:i[f].name,backgroundColor:i[f].backgroundColor??m,clipShape:i[f].clipShape})}Ge()},[]),o.useEffect(()=>{if(!(!b||b.length===0)&&!Ne.current&&pe.current){Ne.current=!0,et(!0);try{const i=le.ElementFactory.createManyFromJSON(b),u=M.getAllArtboards();if(u.length>0){const p=u[0];for(const m of i)M.addElementToArtboard(m.id,p.id)}ae(i);const g=new Set;for(const p of i){const m=p.fontFamily;typeof m=="string"&&m.trim().length>0&&g.add(m)}if(g.size>0&&typeof document<"u"){const p=document.fonts??null,m=Array.from(g).map(f=>{const v=`font-${f.replace(/\s+/g,"-").toLowerCase()}`;let x=document.getElementById(v);return x||(x=document.createElement("link"),x.id=v,x.rel="stylesheet",x.href=`https://fonts.googleapis.com/css2?family=${f.replace(/\s+/g,"+")}:wght@400;700&display=swap`,document.head.appendChild(x)),new Promise(D=>{if(x.sheet){D(f);return}const O=()=>D(f);x.addEventListener("load",O,{once:!0}),x.addEventListener("error",O,{once:!0}),setTimeout(O,4e3)})});Promise.all(m).then(f=>{if(p)return Promise.all(f.flatMap(v=>[p.load(`400 16px "${v}"`).catch(()=>{}),p.load(`700 16px "${v}"`).catch(()=>{})]))}).then(()=>{ae(f=>f.slice())})}}catch(i){V.error("Failed to load initial elements:",i);const u=i instanceof Error?i:new Error(String(i));N({category:"import",message:`Failed to load initial elements: ${u.message}`,originalError:u,recoverable:!0})}}},[b,M,ae,N]),o.useEffect(()=>{if(!c){be.current=!0;return}const i=H.find(u=>u.name===c);if(i){const u=M.getActiveArtboard();(u==null?void 0:u.name)!==c&&Je(i.id),be.current=!0}},[c,H]),o.useEffect(()=>{if(!z||ge.current===z)return;if(K.length>0){ge.current=z;return}ge.current=z,(async()=>{ce("loading"),he(null);try{const u=M.getAllArtboards();if(u.length===0)throw new Error("No artboards available");const g=[];for(const p of u){const m=s==null?void 0:s.find(x=>x.name===p.name),f=(m==null?void 0:m.scaleMode)||Se,v=await Et(z,{artboard:{width:p.width,height:p.height,x:p.x,y:p.y},alignment:(m==null?void 0:m.fitAlign)||ye,scale:Ae,scaleMode:f,marginTop:m==null?void 0:m.fitMarginTop,marginRight:m==null?void 0:m.fitMarginRight,marginBottom:m==null?void 0:m.fitMarginBottom,marginLeft:m==null?void 0:m.fitMarginLeft});v.success&&v.element?(M.addElementToArtboard(v.element.id,p.id),g.push(v.element)):V.error("Failed to load image for artboard:",p.name,v.error)}if(g.length>0)ae(p=>[...p,...g]),ce("success"),A==null||A(z);else{const p=new Error("Failed to load image into any artboard");ce("error"),he(p),h==null||h(z,p),N({category:"image",message:p.message,originalError:p,recoverable:!0})}}catch(u){const g=u instanceof Error?u:new Error(String(u));ce("error"),he(g),h==null||h(z,g),N({category:"image",message:g.message,originalError:g,recoverable:!0})}})()},[z,ye,Ae,Se]),o.useEffect(()=>{L==null||L(He)},[He,L]),o.useEffect(()=>{if(!S)return;const i=M.getActiveArtboard(),u={elements:K.map(g=>g.toJSON()),artboards:H.map(g=>({name:g.name,width:g.width,height:g.height,clipShape:g.clipShape,backgroundColor:g.backgroundColor})),activeArtboard:(i==null?void 0:i.name)||"Design"};S(u)},[K,H,S]),o.useEffect(()=>{if(!d||!be.current)return;const i=M.getActiveArtboard();i&&d(i.name)},[M.getActiveArtboardId()]);const nt=o.useCallback(async()=>{if(!y&&!w)return;const i=++rt.current,u=Date.now();let g=X;if(j>0&&isFinite(j))for(const f of H){const v=Ee(f.width,f.height,X,j);g=Math.min(g,v)}const p=M.getActiveArtboard(),m=(p==null?void 0:p.id)??"unknown";w==null||w({status:"rendering",artboardId:m}),tt.current=u;try{let f;const v={format:ee,scale:g,quality:te};if(q==="blob")if(ue){const x=await ie(v);f={};for(const[D,O]of Object.entries(x)){const $=H.find(J=>J.id===D);$&&(f[$.name]=O)}}else{const x=M.getActiveArtboard();if(!x)return;const D=await Q(x.id,v);f={[x.name]:D}}else if(ue){const x=await se(v);f={};for(const[D,O]of Object.entries(x)){const $=H.find(J=>J.id===D);$&&(f[$.name]=O)}}else{const x=M.getActiveArtboard();if(!x)return;const D=await G(x.id,v);f={[x.name]:D}}y==null||y(f),w==null||w({status:"complete",artboardId:m,result:f})}catch(f){const v=f instanceof Error?f.message:String(f);if(v.includes("Canvas ref not available"))return;const x=Date.now()-u;V.error("Export failed (export #"+i+"):",{duration:`${x}ms`,error:v});const D=f instanceof Error?f:new Error(v);w==null||w({status:"error",artboardId:m,error:D}),N({category:"export",message:D.message,originalError:D,artboardId:m,recoverable:!0})}},[y,w,ue,q,X,j,ee,te,G,se,Q,ie,H,M,K,Z,N]);o.useEffect(()=>{we!==void 0&&we>0&&V.warn("autoExportInterval is deprecated and ignored. Use autoExportConfig={{ enabled: true, debounceMs: 100, maxWaitMs: 1000 }} instead.")},[]),o.useEffect(()=>{},[K]);const at=o.useCallback(()=>{if(T==null||T(),w){const i=M.getActiveArtboard();w({status:"scheduled",artboardId:(i==null?void 0:i.id)??"unknown"})}},[T,w,M]),ot=!!b&&b.length>0,xe=$e({isCanvasReady:me,elements:K,hasInitialElements:ot,initialElementsLoaded:_e}),je=o.useRef(!1);o.useEffect(()=>{xe&&!je.current&&(je.current=!0,E==null||E())},[xe,E]),Oe({config:Z?{enabled:Z.enabled??!0,debounceMs:Z.debounceMs??100,maxWaitMs:Z.maxWaitMs??1e3}:{enabled:!1},historyManager:Qe,artboards:H,elements:K,onExport:nt,onExportScheduled:at,isCanvasReady:xe}),o.useEffect(()=>{if(H.length>0&&!me){const i=requestAnimationFrame(()=>{oe(!0)});return()=>cancelAnimationFrame(i)}},[H.length,me,oe]),o.useEffect(()=>()=>{oe(!1)},[oe]);const st=o.useCallback(i=>{N({category:"unknown",message:i.message,originalError:i,recoverable:!1})},[N]);return Be==="loading"?C.jsx("div",{className:W,style:{...F,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"var(--surface, #f5f5f5)"},children:C.jsx(I.Spinner,{size:48})}):Be==="error"&&We?C.jsx("div",{className:W,style:{...F,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"var(--surface, #f5f5f5)",color:"var(--danger, #dc2626)",padding:"1rem"},children:C.jsxs("div",{className:"text-center",children:[C.jsx("div",{className:"font-medium",children:"Failed to load image"}),C.jsx("div",{className:"text-sm mt-1 opacity-70",children:We.message})]})}):C.jsx(I.KitProvider,{kit:re,children:C.jsx("div",{className:`app-modern ${W||""}`,style:{...F,position:"relative"},children:C.jsxs(ze,{onError:st,fallback:(i,u)=>C.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"24px",minHeight:"200px",backgroundColor:"var(--surface, #f5f5f5)",color:"var(--foreground, #333)",fontFamily:"system-ui, sans-serif",textAlign:"center"},children:[C.jsx("div",{style:{fontSize:"18px",fontWeight:600,marginBottom:"8px"},children:"Something went wrong"}),C.jsx("div",{style:{fontSize:"14px",opacity:.7,marginBottom:"16px",maxWidth:"400px"},children:i.message}),C.jsx("button",{onClick:u,style:{padding:"8px 20px",backgroundColor:"var(--primary, #333)",color:"var(--primary-foreground, #fff)",border:"none",borderRadius:"6px",fontSize:"14px",fontWeight:500,cursor:"pointer"},children:"Try again"})]}),children:[!qe&&(Te||Fe?C.jsx("div",{className:Te,style:Fe,children:C.jsx(I.Canvas,{style:{width:"100%"},fitPadding:Re,artboardBorderRadius:Ce,fixedMargin:Ie,maxHeight:ke,showRotationHandle:Me,enableShortcuts:Pe,canvasCutouts:De,pieceGuides:fe,pieceFocus:Le})}):C.jsx(I.Canvas,{style:{width:"100%"},fitPadding:Re,artboardBorderRadius:Ce,fixedMargin:Ie,maxHeight:ke,showRotationHandle:Me,enableShortcuts:Pe,canvasCutouts:De,pieceGuides:fe,pieceFocus:Le})),_]})})})});Xe.displayName="SnowconeCanvasInner";const ve=o.forwardRef((t,e)=>{var s;const{inheritTheme:r,externalProvider:a}=t,n=t.viewPadding??((s=t.layoutConfig)==null?void 0:s.viewPadding),l=C.jsx(Xe,{ref:e,...t});return a?C.jsx(B.ThemeProvider,{defaultTheme:"light",passive:r,children:l}):C.jsx(B.ThemeProvider,{defaultTheme:"light",passive:r,children:C.jsx(B.EditorProvider,{viewPadding:n,children:l})})});ve.displayName="SnowconeCanvas";const Ue=U.createLogger("useCommands");function wt(){const t=B.useEditor(),{undo:e,redo:r,canUndo:a,canRedo:n,executeElementUpdate:l,executeAddElement:s,executeRemoveElement:c,executeReorderElement:d,executeCommandBatch:b,executeCreateArtboard:S,executeDeleteArtboard:L,executeUpdateArtboard:k}=t,y=o.useCallback(()=>{Ue.warn("[useCommands] clearHistory is not yet implemented in EditorContext")},[]),T=o.useCallback(w=>{Ue.warn("[useCommands] clearArtboardHistory is not yet implemented in EditorContext")},[]);return{undo:e,redo:r,canUndo:a,canRedo:n,clearHistory:y,clearArtboardHistory:T,executeElementUpdate:l,executeAddElement:s,executeRemoveElement:c,executeReorderElement:d,executeCreateArtboard:S,executeDeleteArtboard:L,executeUpdateArtboard:k,executeCommandBatch:b}}function yt(){const{selectedElement:t}=B.useEditor();return t??null}function At(){const{isCanvasReady:t}=B.useEditor();return t}const St=()=>{},Rt=[];function Ct(t){const{elementStore:e}=B.useElementsContext(),{executeElementUpdate:r}=B.useCommandContext(),a=o.useMemo(()=>e.getAllByName(t).filter(s=>s instanceof U.TextElement),[e,t]),n=o.useCallback(l=>{for(const s of a){const c=s.clone();c.setText(l),r(s,c)}},[a,r]);return a.length===0?{text:"",setText:St,element:null,elements:Rt,isConnected:!1}:{text:a[0].getText(),setText:n,element:a[0],elements:a,isConnected:!0}}const It=()=>{},kt=[];function Mt(t,e,r){const a=t/e;if(r>=a){const n=e,l=n*r,s=t/l;return{width:l,height:n,cropX:(1-s)/2,cropY:0,cropWidth:s,cropHeight:1}}else{const n=t,l=n/r,s=e/l;return{width:n,height:l,cropX:0,cropY:(1-s)/2,cropWidth:1,cropHeight:s}}}function Tt(t,e){const r=(e==null?void 0:e.fit)??"cover",{elementStore:a,setElements:n}=B.useElementsContext(),{executeElementUpdate:l}=B.useCommandContext(),s=o.useMemo(()=>a.getAllByName(t).filter(y=>y instanceof U.ImageElement),[a,t]),c=o.useRef(new Map);for(const k of s)if(!c.current.has(k.id)){const y=k.transformData;c.current.set(k.id,{width:y.width*y.cropWidth,height:y.height*y.cropHeight})}const d=o.useRef(s);d.current=s;const b=o.useRef(l);b.current=l;const S=o.useRef(n);S.current=n;const L=o.useCallback(k=>{const y=d.current,T=b.current;S.current;for(const w of y){const P=c.current.get(w.id);if(!P)continue;const{width:A,height:h}=P,R=w.clone();R.imageLoaded=!1,R.imageElement=null,R.isCropping=!1,R.imageUrl=k,r==="cover"?(R.preserveDimensions=!0,R.onLoadCallback=E=>{const W=E.imageAspectRatio||1,F=Mt(A,h,W);E.transformData.width=F.width,E.transformData.height=F.height,E.transformData.cropX=F.cropX,E.transformData.cropY=F.cropY,E.transformData.cropWidth=F.cropWidth,E.transformData.cropHeight=F.cropHeight,T(w,E)}):(R.preserveDimensions=!1,R.onLoadCallback=E=>{const W=E.transformData.width,F=E.transformData.height,Y=Math.min(A/W,h/F,1);Y<1&&(E.transformData.width=W*Y,E.transformData.height=F*Y),E.transformData.cropX=0,E.transformData.cropY=0,E.transformData.cropWidth=1,E.transformData.cropHeight=1,T(w,E)}),R.loadImage(k)}},[r]);return s.length===0?{imageUrl:"",setImageUrl:It,element:null,elements:kt,isConnected:!1}:{imageUrl:s[0].imageUrl,setImageUrl:L,element:s[0],elements:s,isConnected:!0}}function Ft(t){const{elementStore:e}=B.useElementsContext();return t?e.getByName(t)??null:null}function Dt(){const{zoom:t,panOffset:e,zoomIn:r,zoomOut:a,zoomToFit:n,resetView:l,setZoom:s,setPanOffset:c}=B.useViewportContext();return{zoom:t,panOffset:e,zoomIn:r,zoomOut:a,zoomToFit:n,resetView:l,setZoom:s,setPanOffset:c}}function Lt(t){var a;const e=((a=t.artboards)==null?void 0:a[0])||{name:"Front",width:800,height:800},r=(t.elements||[]).map(Pt);return{artboards:[{id:"artboard-1",name:e.name||"Front",x:0,y:0,width:e.width||800,height:e.height||800,backgroundColor:e.backgroundColor||"transparent",exportBackground:!1,elements:r,distressTexture:e.distressTexture,imageMask:e.imageMask}]}}function Pt(t){const e=t.type||t.transformType;return e==="image"?Ht(t):{...t,type:e}}function Ht(t){var b;const e=t.transformData||{},r=t.masks&&t.masks.length>0,a=e.width||0,n=e.height||0,l=r?a:a*(e.cropWidth??1),s=r?n:n*(e.cropHeight??1),c={id:t.id,type:"image",x:t.x||0,y:t.y||0,width:l,height:s,rotation:t.rotation||0,imageUrl:t.imageUrl,imageAspectRatio:t.imageAspectRatio};return!r&&(e.cropX!==0||e.cropY!==0||e.cropWidth!==1||e.cropHeight!==1)&&(c.cropX=e.cropX,c.cropY=e.cropY,c.cropWidth=e.cropWidth,c.cropHeight=e.cropHeight,c.needsCropPixelConversion=!0),e.flipHorizontal&&(c.flipHorizontal=e.flipHorizontal),e.flipVertical&&(c.flipVertical=e.flipVertical),e.borderRadius&&(c.borderRadius=e.borderRadius),t.opacity!==void 0&&(c.opacity=t.opacity),t.distressEffect&&(c.distressEffect=t.distressEffect),((b=t.masks)==null?void 0:b.length)>0&&(c.masks=t.masks),t.blendMode&&(c.blendMode=t.blendMode),t.knockoutParts&&(c.knockoutParts=t.knockoutParts),t.stroke&&(c.stroke=t.stroke),c}I.ensureIconsRegistered();exports.ALL_CAPABILITIES=I.ALL_CAPABILITIES;exports.COMPACT_CUSTOMIZER=I.COMPACT_CUSTOMIZER;exports.EMBED_ONLY=I.EMBED_ONLY;exports.MINIMAL_CAPABILITIES=I.MINIMAL_CAPABILITIES;exports.PRO_STUDIO=I.PRO_STUDIO;exports.createKit=I.createKit;exports.extendKit=I.extendKit;exports.resolveKit=I.resolveKit;exports.useArtboards=I.useArtboards;exports.useExport=I.useExport;exports.useLayers=I.useLayers;exports.validateKit=I.validateKit;exports.useEditor=B.useEditor;exports.deserializeState=de.deserializeState;exports.migrateState=de.migrateState;exports.serializeState=de.serializeState;exports.validateState=de.validateState;exports.ErrorBoundary=ze;exports.SnowconeCanvas=ve;exports.default=ve;exports.serializeStateForServer=Lt;exports.useAutoExport=Oe;exports.useCanvasReady=At;exports.useCommands=wt;exports.useContentReady=$e;exports.useElementByName=Ft;exports.useImageBinding=Tt;exports.useSelectedElement=yt;exports.useTextBinding=Ct;exports.useViewport=Dt;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|