@cs-open/react-fabric 0.0.8 → 0.0.12

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.
@@ -1,2 +1,2 @@
1
- "use strict";var n=require("react"),$=require("fabric"),d=require("./useStore.cjs");function v(o,s){const c=d.useStoreApi(),u=n.useRef(null),f=n.useRef("");if(n.useEffect(()=>{if(!o)return;const{canvas:t}=c.getState();if(!t)return;const i=()=>{if(!u.current)return;const e=o.getCoords().map(x=>$.util.sendPointToPlane(x,t.viewportTransform,void 0)),l=`${e[0].x},${e[0].y},${e[2].x-e[0].x},${e[2].y-e[0].y}`;if(l===f.current)return;f.current=l;const y=u.current;Object.assign(y.style,{position:"absolute",left:`${e[0].x}px`,top:`${e[0].y}px`,width:`${e[2].x-e[0].x}px`,height:`${e[2].y-e[0].y}px`})};return t.on("after:render",i),i(),()=>{t.off("after:render",i)}},[o,c]),!n.isValidElement(s))return s;const a=s.props,r=s.ref,p=n.useCallback(t=>{u.current=t,r&&(typeof r=="function"?r(t):r&&(r.current=t))},[r]);return n.cloneElement(s,{...a,ref:p,style:{position:"absolute",...a.style}})}exports.useInstancePosition=v;
1
+ "use strict";var n=require("react"),x=require("fabric"),d=require("./useStore.cjs");function $(i,s){const o=d.useStoreApi(),u=n.useRef(null),c=n.useRef(""),l=n.useCallback(r=>{u.current=r;const t=n.isValidElement(s)?s.ref:void 0;t&&(typeof t=="function"?t(r):t&&(t.current=r))},[s]);if(n.useEffect(()=>{if(!i)return;const{canvas:r}=o.getState();if(!r)return;const t=()=>{if(!u.current)return;const e=i.getCoords().map(y=>x.util.sendPointToPlane(y,r.viewportTransform,void 0)),a=`${e[0].x},${e[0].y},${e[2].x-e[0].x},${e[2].y-e[0].y}`;if(a===c.current)return;c.current=a;const p=u.current;Object.assign(p.style,{position:"absolute",left:`${e[0].x}px`,top:`${e[0].y}px`,width:`${e[2].x-e[0].x}px`,height:`${e[2].y-e[0].y}px`})};return r.on("after:render",t),t(),()=>{r.off("after:render",t)}},[i,o]),!n.isValidElement(s))return null;const f=s.props;return n.cloneElement(s,{...f,ref:l,style:{position:"absolute",...f.style}})}exports.useInstancePosition=$;
2
2
  //# sourceMappingURL=useInstancePosition.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useInstancePosition.cjs","sources":["../../../src/hooks/useInstancePosition.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, cloneElement, isValidElement, type ReactNode } from 'react'\nimport { util } from 'fabric'\nimport type { FabricObject } from 'fabric'\nimport { useStoreApi } from './useStore'\n\n/**\n * 用于同步子元素位置与 Fabric.js 对象位置的 Hook\n * 直接操作 DOM 元素样式,避免频繁的 React 重渲染\n * 同时处理 ref 合并和 children 克隆\n * @param instance Fabric.js 对象实例\n * @param children 需要处理的子元素\n * @returns 处理后的 children\n */\nexport function useInstancePosition(instance: FabricObject | undefined, children: ReactNode) {\n const store = useStoreApi()\n const childElementRef = useRef<HTMLElement | null>(null)\n const lastPositionRef = useRef<string>('')\n\n useEffect(() => {\n if (!instance) return\n\n const { canvas } = store.getState()\n if (!canvas) return\n\n const updatePosition = () => {\n if (!childElementRef.current) return\n\n const sceneCoords = instance.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const newPosition = `${viewportCoords[0].x},${viewportCoords[0].y},${viewportCoords[2].x - viewportCoords[0].x},${viewportCoords[2].y - viewportCoords[0].y}`\n\n if (newPosition === lastPositionRef.current) return\n lastPositionRef.current = newPosition\n\n const element = childElementRef.current\n Object.assign(element.style, {\n position: 'absolute',\n left: `${viewportCoords[0].x}px`,\n top: `${viewportCoords[0].y}px`,\n width: `${viewportCoords[2].x - viewportCoords[0].x}px`,\n height: `${viewportCoords[2].y - viewportCoords[0].y}px`,\n })\n }\n\n canvas.on('after:render', updatePosition)\n updatePosition()\n\n return () => {\n canvas.off('after:render', updatePosition)\n }\n }, [instance, store])\n\n // 处理 children\n if (!isValidElement(children)) return children\n\n const childProps = children.props as any\n const originalRef = (children as any).ref\n\n const handleRef = useCallback(\n (node: any) => {\n childElementRef.current = node\n if (originalRef) {\n if (typeof originalRef === 'function') {\n originalRef(node)\n } else if (originalRef) {\n originalRef.current = node\n }\n }\n },\n [originalRef],\n )\n\n return cloneElement(children, {\n ...childProps,\n ref: handleRef,\n style: {\n position: 'absolute',\n ...childProps.style,\n },\n } as any)\n}\n"],"names":["useInstancePosition","instance","children","store","useStoreApi","childElementRef","useRef","lastPositionRef","useEffect","canvas","updatePosition","viewportCoords","point","util","newPosition","element","isValidElement","childProps","originalRef","handleRef","useCallback","node","cloneElement"],"mappings":"oFAaO,SAASA,EAAoBC,EAAoCC,EAAqB,CAC3F,MAAMC,EAAQC,EAAY,YAAA,EACpBC,EAAkBC,SAA2B,IAAI,EACjDC,EAAkBD,EAAe,OAAA,EAAE,EAsCzC,GApCAE,EAAU,UAAA,IAAM,CACd,GAAI,CAACP,EAAU,OAEf,KAAM,CAAE,OAAAQ,CAAO,EAAIN,EAAM,SAAA,EACzB,GAAI,CAACM,EAAQ,OAEb,MAAMC,EAAiB,IAAM,CAC3B,GAAI,CAACL,EAAgB,QAAS,OAG9B,MAAMM,EADcV,EAAS,YACM,IAAIW,GAASC,OAAK,iBAAiBD,EAAOH,EAAO,kBAAmB,MAAS,CAAC,EAE3GK,EAAc,GAAGH,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,GAE3J,GAAIG,IAAgBP,EAAgB,QAAS,OAC7CA,EAAgB,QAAUO,EAE1B,MAAMC,EAAUV,EAAgB,QAChC,OAAO,OAAOU,EAAQ,MAAO,CAC3B,SAAU,WACV,KAAM,GAAGJ,EAAe,CAAC,EAAE,CAAC,KAC5B,IAAK,GAAGA,EAAe,CAAC,EAAE,CAAC,KAC3B,MAAO,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,KACnD,OAAQ,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IACtD,CAAC,CACH,EAEA,OAAAF,EAAO,GAAG,eAAgBC,CAAc,EACxCA,IAEO,IAAM,CACXD,EAAO,IAAI,eAAgBC,CAAc,CAC3C,CACF,EAAG,CAACT,EAAUE,CAAK,CAAC,EAGhB,CAACa,iBAAed,CAAQ,EAAG,OAAOA,EAEtC,MAAMe,EAAaf,EAAS,MACtBgB,EAAehB,EAAiB,IAEhCiB,EAAYC,EAAAA,YACfC,GAAc,CACbhB,EAAgB,QAAUgB,EACtBH,IACE,OAAOA,GAAgB,WACzBA,EAAYG,CAAI,EACPH,IACTA,EAAY,QAAUG,GAG5B,EACA,CAACH,CAAW,CACd,EAEA,OAAOI,eAAapB,EAAU,CAC5B,GAAGe,EACH,IAAKE,EACL,MAAO,CACL,SAAU,WACV,GAAGF,EAAW,KAChB,CACF,CAAQ,CACV"}
1
+ {"version":3,"file":"useInstancePosition.cjs","sources":["../../../src/hooks/useInstancePosition.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, cloneElement, isValidElement, type ReactNode } from 'react'\nimport { util } from 'fabric'\nimport type { FabricObject } from 'fabric'\nimport { useStoreApi } from './useStore'\n\n/**\n * 用于同步子元素位置与 Fabric.js 对象位置的 Hook\n * 直接操作 DOM 元素样式,避免频繁的 React 重渲染\n * 同时处理 ref 合并和 children 克隆\n * @param instance Fabric.js 对象实例\n * @param children 需要处理的子元素\n * @returns 处理后的 children\n */\nexport function useInstancePosition(instance: FabricObject | undefined, children: ReactNode) {\n const store = useStoreApi()\n const childElementRef = useRef<HTMLElement | null>(null)\n const lastPositionRef = useRef<string>('')\n\n const handleRef = useCallback(\n (node: any) => {\n childElementRef.current = node\n const currentRef = isValidElement(children) ? (children as any).ref : undefined\n if (currentRef) {\n if (typeof currentRef === 'function') {\n currentRef(node)\n } else if (currentRef) {\n currentRef.current = node\n }\n }\n },\n [children],\n )\n\n useEffect(() => {\n if (!instance) return\n\n const { canvas } = store.getState()\n if (!canvas) return\n\n const updatePosition = () => {\n if (!childElementRef.current) return\n\n const sceneCoords = instance.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const newPosition = `${viewportCoords[0].x},${viewportCoords[0].y},${viewportCoords[2].x - viewportCoords[0].x},${viewportCoords[2].y - viewportCoords[0].y}`\n\n if (newPosition === lastPositionRef.current) return\n lastPositionRef.current = newPosition\n\n const element = childElementRef.current\n Object.assign(element.style, {\n position: 'absolute',\n left: `${viewportCoords[0].x}px`,\n top: `${viewportCoords[0].y}px`,\n width: `${viewportCoords[2].x - viewportCoords[0].x}px`,\n height: `${viewportCoords[2].y - viewportCoords[0].y}px`,\n })\n }\n\n canvas.on('after:render', updatePosition)\n updatePosition()\n\n return () => {\n canvas.off('after:render', updatePosition)\n }\n }, [instance, store])\n\n // 处理 children\n if (!isValidElement(children)) return null\n\n const childProps = children.props as any\n\n return cloneElement(children, {\n ...childProps,\n ref: handleRef,\n style: {\n position: 'absolute',\n ...childProps.style,\n },\n } as any)\n}\n"],"names":["useInstancePosition","instance","children","store","useStoreApi","childElementRef","useRef","lastPositionRef","handleRef","useCallback","node","currentRef","isValidElement","useEffect","canvas","updatePosition","viewportCoords","point","util","newPosition","element","childProps","cloneElement"],"mappings":"oFAagB,SAAAA,EAAoBC,EAAoCC,EAAqB,CAC3F,MAAMC,EAAQC,cACRC,EAAAA,EAAkBC,EAAAA,OAA2B,IAAI,EACjDC,EAAkBD,SAAe,EAAE,EAEnCE,EAAYC,EACfC,YAAAA,GAAc,CACbL,EAAgB,QAAUK,EAC1B,MAAMC,EAAaC,iBAAeV,CAAQ,EAAKA,EAAiB,IAAM,OAClES,IACE,OAAOA,GAAe,WACxBA,EAAWD,CAAI,EACNC,IACTA,EAAW,QAAUD,GAG3B,EACA,CAACR,CAAQ,CACX,EAsCA,GApCAW,EAAAA,UAAU,IAAM,CACd,GAAI,CAACZ,EAAU,OAEf,KAAM,CAAE,OAAAa,CAAO,EAAIX,EAAM,SAAA,EACzB,GAAI,CAACW,EAAQ,OAEb,MAAMC,EAAiB,IAAM,CAC3B,GAAI,CAACV,EAAgB,QAAS,OAG9B,MAAMW,EADcf,EAAS,YACM,IAAIgB,GAASC,OAAK,iBAAiBD,EAAOH,EAAO,kBAAmB,MAAS,CAAC,EAE3GK,EAAc,GAAGH,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,GAE3J,GAAIG,IAAgBZ,EAAgB,QAAS,OAC7CA,EAAgB,QAAUY,EAE1B,MAAMC,EAAUf,EAAgB,QAChC,OAAO,OAAOe,EAAQ,MAAO,CAC3B,SAAU,WACV,KAAM,GAAGJ,EAAe,CAAC,EAAE,CAAC,KAC5B,IAAK,GAAGA,EAAe,CAAC,EAAE,CAAC,KAC3B,MAAO,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,KACnD,OAAQ,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IACtD,CAAC,CACH,EAEA,OAAAF,EAAO,GAAG,eAAgBC,CAAc,EACxCA,EAAAA,EAEO,IAAM,CACXD,EAAO,IAAI,eAAgBC,CAAc,CAC3C,CACF,EAAG,CAACd,EAAUE,CAAK,CAAC,EAGhB,CAACS,iBAAeV,CAAQ,EAAG,OAAO,KAEtC,MAAMmB,EAAanB,EAAS,MAE5B,OAAOoB,EAAapB,aAAAA,EAAU,CAC5B,GAAGmB,EACH,IAAKb,EACL,MAAO,CACL,SAAU,WACV,GAAGa,EAAW,KAChB,CACF,CAAQ,CACV"}
@@ -1,2 +1,2 @@
1
- "use strict";var Z=require("zustand/vanilla/shallow"),r=require("react"),u=require("./useStore.cjs");const S=e=>({draggable:e.draggable,selection:e.selection,isDragging:e.isDragging,width:e.width,height:e.height,canvas:e.canvas,setDraggable:e.setDraggable,setIsDragging:e.setIsDragging,lastPosX:e.lastPosX,lastPosY:e.lastPosY,setSelection:e.setSelection,zoomable:e.zoomable,setZoomable:e.setZoomable,scale:e.scale,zoom:e.zoom,defaultCentered:e.defaultCentered,manualZoom:e.manualZoom,maxManualZoom:e.maxManualZoom,minManualZoom:e.minManualZoom,loading:e.loading});function b(){const e=u.useStoreApi(),i=u.useStore(S,Z.shallow),l=r.useMemo(()=>({getCanvas:()=>e.getState().canvas,getNodes:()=>e.getState().nodes.map(a=>({...a})),getState:()=>e.getState,zoomIn:()=>{let{manualZoom:a,canvas:o,fitZoom:m}=e.getState();a+=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;a>n&&(a=n),a<t&&(a=t);const s=a*m;if(o?.backgroundImage&&o){const g=o.getCenterPoint();o.zoomToPoint(g,s)}e.setState({manualZoom:a,zoom:s})},zoomOut:()=>{let{manualZoom:a,canvas:o,fitZoom:m}=e.getState();a-=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;a>n&&(a=n),a<t&&(a=t);const s=a*m;if(o?.backgroundImage&&o){const g=o.getCenterPoint();o.zoomToPoint(g,s)}e.setState({manualZoom:a,zoom:s})},getZoom:()=>e.getState().zoom,resetViewport:(a=1)=>{const{canvas:o,fitZoom:m=1,defaultCentered:n}=e.getState(),t=a*m;if(o){if(n&&o.backgroundImage){const s=o.backgroundImage.width||0,g=o.backgroundImage.height||0,c=(o.width-s*t)/2,d=(o.height-g*t)/2;o.setViewportTransform([t,0,0,t,c,d])}else o.setViewportTransform([t,0,0,t,0,0]);o.requestRenderAll()}e.setState({manualZoom:a,zoom:t})}}),[e]);return r.useMemo(()=>({...l,...i}),[l,i])}exports.useReactFabric=b;
1
+ "use strict";var d=require("zustand/vanilla/shallow"),r=require("react"),u=require("./useStore.cjs");const S=e=>({draggable:e.draggable,selection:e.selection,isDragging:e.isDragging,width:e.width,height:e.height,canvas:e.canvas,setDraggable:e.setDraggable,setIsDragging:e.setIsDragging,lastPosX:e.lastPosX,lastPosY:e.lastPosY,setSelection:e.setSelection,zoomable:e.zoomable,setZoomable:e.setZoomable,scale:e.scale,zoom:e.zoom,fitZoom:e.fitZoom,defaultCentered:e.defaultCentered,manualZoom:e.manualZoom,maxManualZoom:e.maxManualZoom,minManualZoom:e.minManualZoom,loading:e.loading});function f(){const e=u.useStoreApi(),i=u.useStore(S,d.shallow),l=r.useMemo(()=>({getCanvas:()=>e.getState().canvas,getNodes:()=>e.getState().nodes.map(o=>({...o})),getState:()=>e.getState,zoomIn:()=>{let{manualZoom:o,canvas:a,fitZoom:m}=e.getState();o+=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const s=o*m;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,s)}e.setState({manualZoom:o,zoom:s})},zoomOut:()=>{let{manualZoom:o,canvas:a,fitZoom:m}=e.getState();o-=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const s=o*m;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,s)}e.setState({manualZoom:o,zoom:s})},getZoom:()=>e.getState().zoom,resetViewport:(o=1)=>{const{canvas:a,fitZoom:m=1,defaultCentered:n}=e.getState(),t=o*m;if(a){if(n&&a.backgroundImage){const s=a.backgroundImage.width||0,g=a.backgroundImage.height||0,c=(a.width-s*t)/2,Z=(a.height-g*t)/2;a.setViewportTransform([t,0,0,t,c,Z])}else a.setViewportTransform([t,0,0,t,0,0]);a.requestRenderAll()}e.setState({manualZoom:o,zoom:t})}}),[e]);return r.useMemo(()=>({...l,...i}),[l,i])}exports.useReactFabric=f;
2
2
  //# sourceMappingURL=useReactFabric.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useReactFabric.cjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: (manualZoom = 1) => {\n const { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const combinedZoom = manualZoom * fitZoom\n if (canvas) {\n // 先重置 viewport transform\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n const deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n const deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, deltaX, deltaY])\n } else {\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n }\n canvas.requestRenderAll()\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n }\n }, [store])\n\n return useMemo(\n () => ({\n ...generalHelper,\n ...state,\n }),\n [generalHelper, state],\n )\n}\n"],"names":["selector","s","useReactFabric","store","useStoreApi","state","useStore","shallow","generalHelper","useMemo","n","manualZoom","canvas","fitZoom","maxManualZoom","minManualZoom","combinedZoom","center","defaultCentered","bgWidth","bgHeight","deltaX","deltaY"],"mappings":"qGAKA,MAAMA,EAAYC,IAAyB,CACzC,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,WAAYA,EAAE,WACd,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,OAAQA,EAAE,OACV,aAAcA,EAAE,aAChB,cAAeA,EAAE,cACjB,SAAUA,EAAE,SACZ,SAAUA,EAAE,SACZ,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,YAAaA,EAAE,YACf,MAAOA,EAAE,MACT,KAAMA,EAAE,KACR,gBAAiBA,EAAE,gBACnB,WAAYA,EAAE,WACd,cAAeA,EAAE,cACjB,cAAeA,EAAE,cACjB,QAASA,EAAE,OACb,GAEgB,SAAAC,GAAiB,CAC/B,MAAMC,EAAQC,EAAAA,YACRC,EAAAA,EAAQC,EAAAA,SAASN,EAAUO,EAAO,OAAA,EAElCC,EAAgBC,UAAQ,KACrB,CACL,UAAW,IAAMN,EAAM,WAAW,OAClC,SAAU,IAAMA,EAAM,WAAW,MAAM,IAAIO,IAAM,CAAE,GAAGA,CAAE,EAAE,EAC1D,SAAU,IAAMP,EAAM,SAKtB,OAAQ,IAAM,CACZ,GAAI,CAAE,WAAAQ,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,SAAS,EACrDQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAW,EAAA,cACjCY,EAAgBZ,EAAM,WAAW,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,iBACtBA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EAKA,QAAS,IAAM,CACb,GAAI,CAAE,WAAAL,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,SAAA,EAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAS,EAAE,cACjCY,EAAgBZ,EAAM,WAAW,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,iBACtBA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,SAAS,EAAE,KAKhC,cAAe,CAACQ,EAAa,IAAM,CACjC,KAAM,CAAE,OAAAC,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAA,EAEjDa,EAAeL,EAAaE,EAClC,GAAID,EAAQ,CAEV,GAAIM,GAAmBN,EAAO,gBAAiB,CAC7C,MAAMO,EAAUP,EAAO,gBAAgB,OAAS,EAC1CQ,EAAWR,EAAO,gBAAgB,QAAU,EAC5CS,GAAUT,EAAO,MAASO,EAAUH,GAAgB,EACpDM,GAAUV,EAAO,OAAUQ,EAAWJ,GAAgB,EAC5DJ,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAcK,EAAQC,CAAM,CAAC,CAChF,MACEV,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAEtEJ,EAAO,iBAAA,CACT,CAEAT,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,CACF,GACC,CAACb,CAAK,CAAC,EAEV,OAAOM,EAAAA,QACL,KAAO,CACL,GAAGD,EACH,GAAGH,CACL,GACA,CAACG,EAAeH,CAAK,CACvB,CACF"}
1
+ {"version":3,"file":"useReactFabric.cjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n fitZoom: s.fitZoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: (manualZoom = 1) => {\n const { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const combinedZoom = manualZoom * fitZoom\n if (canvas) {\n // 先重置 viewport transform\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n const deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n const deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, deltaX, deltaY])\n } else {\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n }\n canvas.requestRenderAll()\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n }\n }, [store])\n\n return useMemo(\n () => ({\n ...generalHelper,\n ...state,\n }),\n [generalHelper, state],\n )\n}\n"],"names":["selector","s","useReactFabric","store","useStoreApi","state","useStore","shallow","generalHelper","useMemo","n","manualZoom","canvas","fitZoom","maxManualZoom","minManualZoom","combinedZoom","center","defaultCentered","bgWidth","bgHeight","deltaX","deltaY"],"mappings":"qGAKA,MAAMA,EAAYC,IAAyB,CACzC,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,WAAYA,EAAE,WACd,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,OAAQA,EAAE,OACV,aAAcA,EAAE,aAChB,cAAeA,EAAE,cACjB,SAAUA,EAAE,SACZ,SAAUA,EAAE,SACZ,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,YAAaA,EAAE,YACf,MAAOA,EAAE,MACT,KAAMA,EAAE,KACR,QAASA,EAAE,QACX,gBAAiBA,EAAE,gBACnB,WAAYA,EAAE,WACd,cAAeA,EAAE,cACjB,cAAeA,EAAE,cACjB,QAASA,EAAE,OACb,YAEgBC,GAAiB,CAC/B,MAAMC,EAAQC,EAAAA,YAAAA,EACRC,EAAQC,EAAAA,SAASN,EAAUO,SAAO,EAElCC,EAAgBC,EAAAA,QAAQ,KACrB,CACL,UAAW,IAAMN,EAAM,WAAW,OAClC,SAAU,IAAMA,EAAM,SAAA,EAAW,MAAM,IAAIO,IAAM,CAAE,GAAGA,CAAE,EAAE,EAC1D,SAAU,IAAMP,EAAM,SAKtB,OAAQ,IAAM,CACZ,GAAI,CAAE,WAAAQ,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EAKA,QAAS,IAAM,CACb,GAAI,CAAE,WAAAL,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,WAAW,KAKhC,cAAe,CAACQ,EAAa,IAAM,CACjC,KAAM,CAAE,OAAAC,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAS,EAE1Da,EAAeL,EAAaE,EAClC,GAAID,EAAQ,CAEV,GAAIM,GAAmBN,EAAO,gBAAiB,CAC7C,MAAMO,EAAUP,EAAO,gBAAgB,OAAS,EAC1CQ,EAAWR,EAAO,gBAAgB,QAAU,EAC5CS,GAAUT,EAAO,MAASO,EAAUH,GAAgB,EACpDM,GAAUV,EAAO,OAAUQ,EAAWJ,GAAgB,EAC5DJ,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAcK,EAAQC,CAAM,CAAC,CAChF,MACEV,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAEtEJ,EAAO,kBACT,CAEAT,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,CACF,GACC,CAACb,CAAK,CAAC,EAEV,OAAOM,EAAAA,QACL,KAAO,CACL,GAAGD,EACH,GAAGH,CACL,GACA,CAACG,EAAeH,CAAK,CACvB,CACF"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("./container/ReactFabric/index.cjs"),r=require("./hooks/useReactFabric.cjs"),a=require("./hooks/useZoom.cjs"),i=require("./components/BackgroundImage/index.cjs"),u=require("./components/Canvas/index.cjs"),d=require("./components/Group/index.cjs"),t=require("./components/NodeToolbarPortal/index.cjs"),l=require("./components/ReactFabricProvider.cjs"),n=require("./components/Rect/index.cjs"),v=require("./components/Control/index.cjs"),q=require("./components/Image/index.cjs"),c=require("./components/Control2/index.cjs"),f=require("./components/Text/index.cjs"),x=require("./components/Path/index.cjs"),o=require("./components/Line/index.cjs"),$=require("./components/Ellipse/index.cjs"),F=require("./components/IText/index.cjs"),P=require("./components/Textbox/index.cjs"),b=require("./components/WavyLine/index.cjs"),s=require("./components/Objects/index.cjs"),R=require("./plugins/FreeRect.cjs"),g=require("./plugins/GridLine.cjs"),T=require("./plugins/Pinch.cjs"),m=require("./plugins/FreeDraw.cjs"),h=require("./plugins/FreeText.cjs");exports.ReactFabric=e.default,exports.useReactFabric=r.useReactFabric,exports.useZoom=a.useZoom,exports.BackgroundImage=i.default,exports.Canvas=u.default,exports.Group=d.default,exports.NodeToolbarPortal=t.default,exports.ReactFabricProvider=l.ReactFabricProvider,exports.Rect=n.default,exports.Control=v.default,exports.Image=q.default,exports.Control2=c.default,exports.Text=f.default,exports.Path=x.default,exports.Line=o.default,exports.Ellipse=$.default,exports.IText=F.default,exports.Textbox=P.default,exports.WavyLine=b.default,exports.Objects=s.default,exports.PluginFreeRect=R.default,exports.PluginGrid=g.default,exports.PluginPinch=T.default,exports.PluginFreeDraw=m.default,exports.PluginFreeText=h.default;
1
+ "use strict";var r=require("./container/ReactFabric/index.cjs"),a=require("./hooks/useReactFabric.cjs"),i=require("./hooks/useZoom.cjs"),e=require("./hooks/useStore.cjs"),u=require("./components/BackgroundImage/index.cjs"),t=require("./components/Canvas/index.cjs"),d=require("./components/Group/index.cjs"),l=require("./components/NodeToolbarPortal/index.cjs"),n=require("./components/ReactFabricProvider.cjs"),v=require("./components/Rect/index.cjs"),q=require("./components/Control/index.cjs"),o=require("./components/Image/index.cjs"),f=require("./components/Control2/index.cjs"),x=require("./components/Text/index.cjs"),c=require("./components/Path/index.cjs"),s=require("./components/Line/index.cjs"),$=require("./components/Ellipse/index.cjs"),P=require("./components/IText/index.cjs"),F=require("./components/Textbox/index.cjs"),b=require("./components/Polyline/index.cjs"),g=require("./components/WavyLine/index.cjs"),R=require("./components/Objects/index.cjs"),T=require("./plugins/FreeRect.cjs"),m=require("./plugins/GridLine.cjs"),S=require("./plugins/Pinch.cjs"),h=require("./plugins/FreeDraw.cjs"),p=require("./plugins/FreeText.cjs"),k=require("./plugins/Mask.cjs");exports.ReactFabric=r.default,exports.useReactFabric=a.useReactFabric,exports.useZoom=i.useZoom,exports.useStore=e.useStore,exports.useStoreApi=e.useStoreApi,exports.BackgroundImage=u.default,exports.Canvas=t.default,exports.Group=d.default,exports.NodeToolbarPortal=l.default,exports.ReactFabricProvider=n.ReactFabricProvider,exports.Rect=v.default,exports.Control=q.default,exports.Image=o.default,exports.Control2=f.default,exports.Text=x.default,exports.Path=c.default,exports.Line=s.default,exports.Ellipse=$.default,exports.IText=P.default,exports.Textbox=F.default,exports.Polyline=b.default,exports.WavyLine=g.default,exports.Objects=R.default,exports.PluginFreeRect=T.default,exports.PluginGrid=m.default,exports.PluginPinch=S.default,exports.PluginFreeDraw=h.default,exports.PluginFreeText=p.default,exports.PluginMask=k.default;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("./FreeRect.cjs"),r=require("./GridLine.cjs"),i=require("./Pinch.cjs"),u=require("./FreeDraw.cjs"),a=require("./FreeText.cjs");exports.PluginFreeRect=e.default,exports.PluginGrid=r.default,exports.PluginPinch=i.default,exports.PluginFreeDraw=u.default,exports.PluginFreeText=a.default;
1
+ "use strict";var e=require("./FreeRect.cjs"),r=require("./GridLine.cjs"),u=require("./Pinch.cjs"),i=require("./FreeDraw.cjs"),a=require("./FreeText.cjs"),l=require("./Mask.cjs");exports.PluginFreeRect=e.default,exports.PluginGrid=r.default,exports.PluginPinch=u.default,exports.PluginFreeDraw=i.default,exports.PluginFreeText=a.default,exports.PluginMask=l.default;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,2 @@
1
+ "use client";import{Polyline as p}from"fabric";import{forwardRef as a,useImperativeHandle as u,memo as f}from"react";import{useCreateObject as l}from"../../hooks/useCreateObject.mjs";import{useSplitProps as c}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as d}from"../../hooks/useInstancePosition.mjs";const P=a(({group:e,points:o,children:t,...i},s)=>{const[m,n]=c(i),r=l({Constructor:p,param:o,attributes:n,group:e,listeners:m});return u(s,()=>r,[r]),d(r,t)});var b=f(P);export{b as default};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../../../src/components/Polyline/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { Polyline as BasePolyline } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type PolylineProps<T = unknown> = Partial<ConstructorParameters<typeof BasePolyline>[1] & AllObjectEvents> & {\n group?: BaseGroup\n path?: string\n children?: ReactNode\n} & T\n\nconst Polyline = forwardRef<BasePolyline | undefined, PolylineProps>(({ group, points, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: BasePolyline,\n param: points,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(Polyline)\n"],"names":["Polyline","forwardRef","group","points","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","BasePolyline","useImperativeHandle","useInstancePosition","memo"],"mappings":"+TAcA,MAAMA,EAAWC,EAAoD,CAAC,CAAE,MAAAC,EAAO,OAAAC,EAAQ,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACnH,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAaC,EACb,MAAOT,EACP,WAAAK,EACA,MAAAN,EACA,UAAAK,CACF,CAAC,EAED,OAAAM,EAAoBP,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CI,EAAoBJ,EAAUN,CAAQ,CAC/C,CAAC,EAED,MAAeW,EAAKf,CAAQ"}
@@ -1,2 +1,2 @@
1
- "use client";import{useRef as a,useEffect as m,isValidElement as $,useCallback as d,cloneElement as b}from"react";import{util as g}from"fabric";import{useStoreApi as h}from"./useStore.mjs";function v(o,n){const u=h(),s=a(null),f=a("");if(m(()=>{if(!o)return;const{canvas:t}=u.getState();if(!t)return;const i=()=>{if(!s.current)return;const e=o.getCoords().map(y=>g.sendPointToPlane(y,t.viewportTransform,void 0)),p=`${e[0].x},${e[0].y},${e[2].x-e[0].x},${e[2].y-e[0].y}`;if(p===f.current)return;f.current=p;const x=s.current;Object.assign(x.style,{position:"absolute",left:`${e[0].x}px`,top:`${e[0].y}px`,width:`${e[2].x-e[0].x}px`,height:`${e[2].y-e[0].y}px`})};return t.on("after:render",i),i(),()=>{t.off("after:render",i)}},[o,u]),!$(n))return n;const c=n.props,r=n.ref,l=d(t=>{s.current=t,r&&(typeof r=="function"?r(t):r&&(r.current=t))},[r]);return b(n,{...c,ref:l,style:{position:"absolute",...c.style}})}export{v as useInstancePosition};
1
+ "use client";import{useRef as l,useCallback as m,isValidElement as p,useEffect as d,cloneElement as $}from"react";import{util as b}from"fabric";import{useStoreApi as g}from"./useStore.mjs";function v(o,n){const i=g(),s=l(null),u=l(""),a=m(r=>{s.current=r;const e=p(n)?n.ref:void 0;e&&(typeof e=="function"?e(r):e&&(e.current=r))},[n]);if(d(()=>{if(!o)return;const{canvas:r}=i.getState();if(!r)return;const e=()=>{if(!s.current)return;const t=o.getCoords().map(y=>b.sendPointToPlane(y,r.viewportTransform,void 0)),f=`${t[0].x},${t[0].y},${t[2].x-t[0].x},${t[2].y-t[0].y}`;if(f===u.current)return;u.current=f;const x=s.current;Object.assign(x.style,{position:"absolute",left:`${t[0].x}px`,top:`${t[0].y}px`,width:`${t[2].x-t[0].x}px`,height:`${t[2].y-t[0].y}px`})};return r.on("after:render",e),e(),()=>{r.off("after:render",e)}},[o,i]),!p(n))return null;const c=n.props;return $(n,{...c,ref:a,style:{position:"absolute",...c.style}})}export{v as useInstancePosition};
2
2
  //# sourceMappingURL=useInstancePosition.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useInstancePosition.mjs","sources":["../../../src/hooks/useInstancePosition.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, cloneElement, isValidElement, type ReactNode } from 'react'\nimport { util } from 'fabric'\nimport type { FabricObject } from 'fabric'\nimport { useStoreApi } from './useStore'\n\n/**\n * 用于同步子元素位置与 Fabric.js 对象位置的 Hook\n * 直接操作 DOM 元素样式,避免频繁的 React 重渲染\n * 同时处理 ref 合并和 children 克隆\n * @param instance Fabric.js 对象实例\n * @param children 需要处理的子元素\n * @returns 处理后的 children\n */\nexport function useInstancePosition(instance: FabricObject | undefined, children: ReactNode) {\n const store = useStoreApi()\n const childElementRef = useRef<HTMLElement | null>(null)\n const lastPositionRef = useRef<string>('')\n\n useEffect(() => {\n if (!instance) return\n\n const { canvas } = store.getState()\n if (!canvas) return\n\n const updatePosition = () => {\n if (!childElementRef.current) return\n\n const sceneCoords = instance.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const newPosition = `${viewportCoords[0].x},${viewportCoords[0].y},${viewportCoords[2].x - viewportCoords[0].x},${viewportCoords[2].y - viewportCoords[0].y}`\n\n if (newPosition === lastPositionRef.current) return\n lastPositionRef.current = newPosition\n\n const element = childElementRef.current\n Object.assign(element.style, {\n position: 'absolute',\n left: `${viewportCoords[0].x}px`,\n top: `${viewportCoords[0].y}px`,\n width: `${viewportCoords[2].x - viewportCoords[0].x}px`,\n height: `${viewportCoords[2].y - viewportCoords[0].y}px`,\n })\n }\n\n canvas.on('after:render', updatePosition)\n updatePosition()\n\n return () => {\n canvas.off('after:render', updatePosition)\n }\n }, [instance, store])\n\n // 处理 children\n if (!isValidElement(children)) return children\n\n const childProps = children.props as any\n const originalRef = (children as any).ref\n\n const handleRef = useCallback(\n (node: any) => {\n childElementRef.current = node\n if (originalRef) {\n if (typeof originalRef === 'function') {\n originalRef(node)\n } else if (originalRef) {\n originalRef.current = node\n }\n }\n },\n [originalRef],\n )\n\n return cloneElement(children, {\n ...childProps,\n ref: handleRef,\n style: {\n position: 'absolute',\n ...childProps.style,\n },\n } as any)\n}\n"],"names":["useInstancePosition","instance","children","store","useStoreApi","childElementRef","useRef","lastPositionRef","useEffect","canvas","updatePosition","viewportCoords","point","util","newPosition","element","isValidElement","childProps","originalRef","handleRef","useCallback","node","cloneElement"],"mappings":"6LAaO,SAASA,EAAoBC,EAAoCC,EAAqB,CAC3F,MAAMC,EAAQC,EAAY,EACpBC,EAAkBC,EAA2B,IAAI,EACjDC,EAAkBD,EAAe,EAAE,EAsCzC,GApCAE,EAAU,IAAM,CACd,GAAI,CAACP,EAAU,OAEf,KAAM,CAAE,OAAAQ,CAAO,EAAIN,EAAM,SAAA,EACzB,GAAI,CAACM,EAAQ,OAEb,MAAMC,EAAiB,IAAM,CAC3B,GAAI,CAACL,EAAgB,QAAS,OAG9B,MAAMM,EADcV,EAAS,YACM,IAAIW,GAASC,EAAK,iBAAiBD,EAAOH,EAAO,kBAAmB,MAAS,CAAC,EAE3GK,EAAc,GAAGH,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,GAE3J,GAAIG,IAAgBP,EAAgB,QAAS,OAC7CA,EAAgB,QAAUO,EAE1B,MAAMC,EAAUV,EAAgB,QAChC,OAAO,OAAOU,EAAQ,MAAO,CAC3B,SAAU,WACV,KAAM,GAAGJ,EAAe,CAAC,EAAE,CAAC,KAC5B,IAAK,GAAGA,EAAe,CAAC,EAAE,CAAC,KAC3B,MAAO,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,KACnD,OAAQ,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IACtD,CAAC,CACH,EAEA,OAAAF,EAAO,GAAG,eAAgBC,CAAc,EACxCA,IAEO,IAAM,CACXD,EAAO,IAAI,eAAgBC,CAAc,CAC3C,CACF,EAAG,CAACT,EAAUE,CAAK,CAAC,EAGhB,CAACa,EAAed,CAAQ,EAAG,OAAOA,EAEtC,MAAMe,EAAaf,EAAS,MACtBgB,EAAehB,EAAiB,IAEhCiB,EAAYC,EACfC,GAAc,CACbhB,EAAgB,QAAUgB,EACtBH,IACE,OAAOA,GAAgB,WACzBA,EAAYG,CAAI,EACPH,IACTA,EAAY,QAAUG,GAG5B,EACA,CAACH,CAAW,CACd,EAEA,OAAOI,EAAapB,EAAU,CAC5B,GAAGe,EACH,IAAKE,EACL,MAAO,CACL,SAAU,WACV,GAAGF,EAAW,KAChB,CACF,CAAQ,CACV"}
1
+ {"version":3,"file":"useInstancePosition.mjs","sources":["../../../src/hooks/useInstancePosition.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, cloneElement, isValidElement, type ReactNode } from 'react'\nimport { util } from 'fabric'\nimport type { FabricObject } from 'fabric'\nimport { useStoreApi } from './useStore'\n\n/**\n * 用于同步子元素位置与 Fabric.js 对象位置的 Hook\n * 直接操作 DOM 元素样式,避免频繁的 React 重渲染\n * 同时处理 ref 合并和 children 克隆\n * @param instance Fabric.js 对象实例\n * @param children 需要处理的子元素\n * @returns 处理后的 children\n */\nexport function useInstancePosition(instance: FabricObject | undefined, children: ReactNode) {\n const store = useStoreApi()\n const childElementRef = useRef<HTMLElement | null>(null)\n const lastPositionRef = useRef<string>('')\n\n const handleRef = useCallback(\n (node: any) => {\n childElementRef.current = node\n const currentRef = isValidElement(children) ? (children as any).ref : undefined\n if (currentRef) {\n if (typeof currentRef === 'function') {\n currentRef(node)\n } else if (currentRef) {\n currentRef.current = node\n }\n }\n },\n [children],\n )\n\n useEffect(() => {\n if (!instance) return\n\n const { canvas } = store.getState()\n if (!canvas) return\n\n const updatePosition = () => {\n if (!childElementRef.current) return\n\n const sceneCoords = instance.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const newPosition = `${viewportCoords[0].x},${viewportCoords[0].y},${viewportCoords[2].x - viewportCoords[0].x},${viewportCoords[2].y - viewportCoords[0].y}`\n\n if (newPosition === lastPositionRef.current) return\n lastPositionRef.current = newPosition\n\n const element = childElementRef.current\n Object.assign(element.style, {\n position: 'absolute',\n left: `${viewportCoords[0].x}px`,\n top: `${viewportCoords[0].y}px`,\n width: `${viewportCoords[2].x - viewportCoords[0].x}px`,\n height: `${viewportCoords[2].y - viewportCoords[0].y}px`,\n })\n }\n\n canvas.on('after:render', updatePosition)\n updatePosition()\n\n return () => {\n canvas.off('after:render', updatePosition)\n }\n }, [instance, store])\n\n // 处理 children\n if (!isValidElement(children)) return null\n\n const childProps = children.props as any\n\n return cloneElement(children, {\n ...childProps,\n ref: handleRef,\n style: {\n position: 'absolute',\n ...childProps.style,\n },\n } as any)\n}\n"],"names":["useInstancePosition","instance","children","store","useStoreApi","childElementRef","useRef","lastPositionRef","handleRef","useCallback","node","currentRef","isValidElement","useEffect","canvas","updatePosition","viewportCoords","point","util","newPosition","element","childProps","cloneElement"],"mappings":"6LAagB,SAAAA,EAAoBC,EAAoCC,EAAqB,CAC3F,MAAMC,EAAQC,EACRC,EAAAA,EAAkBC,EAA2B,IAAI,EACjDC,EAAkBD,EAAe,EAAE,EAEnCE,EAAYC,EACfC,GAAc,CACbL,EAAgB,QAAUK,EAC1B,MAAMC,EAAaC,EAAeV,CAAQ,EAAKA,EAAiB,IAAM,OAClES,IACE,OAAOA,GAAe,WACxBA,EAAWD,CAAI,EACNC,IACTA,EAAW,QAAUD,GAG3B,EACA,CAACR,CAAQ,CACX,EAsCA,GApCAW,EAAU,IAAM,CACd,GAAI,CAACZ,EAAU,OAEf,KAAM,CAAE,OAAAa,CAAO,EAAIX,EAAM,SAAA,EACzB,GAAI,CAACW,EAAQ,OAEb,MAAMC,EAAiB,IAAM,CAC3B,GAAI,CAACV,EAAgB,QAAS,OAG9B,MAAMW,EADcf,EAAS,YACM,IAAIgB,GAASC,EAAK,iBAAiBD,EAAOH,EAAO,kBAAmB,MAAS,CAAC,EAE3GK,EAAc,GAAGH,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,GAE3J,GAAIG,IAAgBZ,EAAgB,QAAS,OAC7CA,EAAgB,QAAUY,EAE1B,MAAMC,EAAUf,EAAgB,QAChC,OAAO,OAAOe,EAAQ,MAAO,CAC3B,SAAU,WACV,KAAM,GAAGJ,EAAe,CAAC,EAAE,CAAC,KAC5B,IAAK,GAAGA,EAAe,CAAC,EAAE,CAAC,KAC3B,MAAO,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,KACnD,OAAQ,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IACtD,CAAC,CACH,EAEA,OAAAF,EAAO,GAAG,eAAgBC,CAAc,EACxCA,EAAAA,EAEO,IAAM,CACXD,EAAO,IAAI,eAAgBC,CAAc,CAC3C,CACF,EAAG,CAACd,EAAUE,CAAK,CAAC,EAGhB,CAACS,EAAeV,CAAQ,EAAG,OAAO,KAEtC,MAAMmB,EAAanB,EAAS,MAE5B,OAAOoB,EAAapB,EAAU,CAC5B,GAAGmB,EACH,IAAKb,EACL,MAAO,CACL,SAAU,WACV,GAAGa,EAAW,KAChB,CACF,CAAQ,CACV"}
@@ -1,2 +1,2 @@
1
- "use client";import{shallow as d}from"zustand/vanilla/shallow";import{useMemo as r}from"react";import{useStoreApi as Z,useStore as S}from"./useStore.mjs";const f=e=>({draggable:e.draggable,selection:e.selection,isDragging:e.isDragging,width:e.width,height:e.height,canvas:e.canvas,setDraggable:e.setDraggable,setIsDragging:e.setIsDragging,lastPosX:e.lastPosX,lastPosY:e.lastPosY,setSelection:e.setSelection,zoomable:e.zoomable,setZoomable:e.setZoomable,scale:e.scale,zoom:e.zoom,defaultCentered:e.defaultCentered,manualZoom:e.manualZoom,maxManualZoom:e.maxManualZoom,minManualZoom:e.minManualZoom,loading:e.loading});function b(){const e=Z(),i=S(f,d),l=r(()=>({getCanvas:()=>e.getState().canvas,getNodes:()=>e.getState().nodes.map(o=>({...o})),getState:()=>e.getState,zoomIn:()=>{let{manualZoom:o,canvas:a,fitZoom:s}=e.getState();o+=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const m=o*s;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,m)}e.setState({manualZoom:o,zoom:m})},zoomOut:()=>{let{manualZoom:o,canvas:a,fitZoom:s}=e.getState();o-=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const m=o*s;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,m)}e.setState({manualZoom:o,zoom:m})},getZoom:()=>e.getState().zoom,resetViewport:(o=1)=>{const{canvas:a,fitZoom:s=1,defaultCentered:n}=e.getState(),t=o*s;if(a){if(n&&a.backgroundImage){const m=a.backgroundImage.width||0,g=a.backgroundImage.height||0,u=(a.width-m*t)/2,c=(a.height-g*t)/2;a.setViewportTransform([t,0,0,t,u,c])}else a.setViewportTransform([t,0,0,t,0,0]);a.requestRenderAll()}e.setState({manualZoom:o,zoom:t})}}),[e]);return r(()=>({...l,...i}),[l,i])}export{b as useReactFabric};
1
+ "use client";import{shallow as Z}from"zustand/vanilla/shallow";import{useMemo as r}from"react";import{useStoreApi as d,useStore as f}from"./useStore.mjs";const S=o=>({draggable:o.draggable,selection:o.selection,isDragging:o.isDragging,width:o.width,height:o.height,canvas:o.canvas,setDraggable:o.setDraggable,setIsDragging:o.setIsDragging,lastPosX:o.lastPosX,lastPosY:o.lastPosY,setSelection:o.setSelection,zoomable:o.zoomable,setZoomable:o.setZoomable,scale:o.scale,zoom:o.zoom,fitZoom:o.fitZoom,defaultCentered:o.defaultCentered,manualZoom:o.manualZoom,maxManualZoom:o.maxManualZoom,minManualZoom:o.minManualZoom,loading:o.loading});function b(){const o=d(),i=f(S,Z),l=r(()=>({getCanvas:()=>o.getState().canvas,getNodes:()=>o.getState().nodes.map(e=>({...e})),getState:()=>o.getState,zoomIn:()=>{let{manualZoom:e,canvas:a,fitZoom:s}=o.getState();e+=.2;const n=o.getState().maxManualZoom,t=o.getState().minManualZoom;e>n&&(e=n),e<t&&(e=t);const m=e*s;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,m)}o.setState({manualZoom:e,zoom:m})},zoomOut:()=>{let{manualZoom:e,canvas:a,fitZoom:s}=o.getState();e-=.2;const n=o.getState().maxManualZoom,t=o.getState().minManualZoom;e>n&&(e=n),e<t&&(e=t);const m=e*s;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,m)}o.setState({manualZoom:e,zoom:m})},getZoom:()=>o.getState().zoom,resetViewport:(e=1)=>{const{canvas:a,fitZoom:s=1,defaultCentered:n}=o.getState(),t=e*s;if(a){if(n&&a.backgroundImage){const m=a.backgroundImage.width||0,g=a.backgroundImage.height||0,u=(a.width-m*t)/2,c=(a.height-g*t)/2;a.setViewportTransform([t,0,0,t,u,c])}else a.setViewportTransform([t,0,0,t,0,0]);a.requestRenderAll()}o.setState({manualZoom:e,zoom:t})}}),[o]);return r(()=>({...l,...i}),[l,i])}export{b as useReactFabric};
2
2
  //# sourceMappingURL=useReactFabric.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useReactFabric.mjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: (manualZoom = 1) => {\n const { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const combinedZoom = manualZoom * fitZoom\n if (canvas) {\n // 先重置 viewport transform\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n const deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n const deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, deltaX, deltaY])\n } else {\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n }\n canvas.requestRenderAll()\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n }\n }, [store])\n\n return useMemo(\n () => ({\n ...generalHelper,\n ...state,\n }),\n [generalHelper, state],\n )\n}\n"],"names":["selector","s","useReactFabric","store","useStoreApi","state","useStore","shallow","generalHelper","useMemo","n","manualZoom","canvas","fitZoom","maxManualZoom","minManualZoom","combinedZoom","center","defaultCentered","bgWidth","bgHeight","deltaX","deltaY"],"mappings":"0JAKA,MAAMA,EAAYC,IAAyB,CACzC,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,WAAYA,EAAE,WACd,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,OAAQA,EAAE,OACV,aAAcA,EAAE,aAChB,cAAeA,EAAE,cACjB,SAAUA,EAAE,SACZ,SAAUA,EAAE,SACZ,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,YAAaA,EAAE,YACf,MAAOA,EAAE,MACT,KAAMA,EAAE,KACR,gBAAiBA,EAAE,gBACnB,WAAYA,EAAE,WACd,cAAeA,EAAE,cACjB,cAAeA,EAAE,cACjB,QAASA,EAAE,OACb,GAEgB,SAAAC,GAAiB,CAC/B,MAAMC,EAAQC,EACRC,EAAAA,EAAQC,EAASN,EAAUO,CAAO,EAElCC,EAAgBC,EAAQ,KACrB,CACL,UAAW,IAAMN,EAAM,WAAW,OAClC,SAAU,IAAMA,EAAM,WAAW,MAAM,IAAIO,IAAM,CAAE,GAAGA,CAAE,EAAE,EAC1D,SAAU,IAAMP,EAAM,SAKtB,OAAQ,IAAM,CACZ,GAAI,CAAE,WAAAQ,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,SAAS,EACrDQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAW,EAAA,cACjCY,EAAgBZ,EAAM,WAAW,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,iBACtBA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EAKA,QAAS,IAAM,CACb,GAAI,CAAE,WAAAL,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,SAAA,EAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAS,EAAE,cACjCY,EAAgBZ,EAAM,WAAW,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,iBACtBA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,SAAS,EAAE,KAKhC,cAAe,CAACQ,EAAa,IAAM,CACjC,KAAM,CAAE,OAAAC,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAA,EAEjDa,EAAeL,EAAaE,EAClC,GAAID,EAAQ,CAEV,GAAIM,GAAmBN,EAAO,gBAAiB,CAC7C,MAAMO,EAAUP,EAAO,gBAAgB,OAAS,EAC1CQ,EAAWR,EAAO,gBAAgB,QAAU,EAC5CS,GAAUT,EAAO,MAASO,EAAUH,GAAgB,EACpDM,GAAUV,EAAO,OAAUQ,EAAWJ,GAAgB,EAC5DJ,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAcK,EAAQC,CAAM,CAAC,CAChF,MACEV,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAEtEJ,EAAO,iBAAA,CACT,CAEAT,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,CACF,GACC,CAACb,CAAK,CAAC,EAEV,OAAOM,EACL,KAAO,CACL,GAAGD,EACH,GAAGH,CACL,GACA,CAACG,EAAeH,CAAK,CACvB,CACF"}
1
+ {"version":3,"file":"useReactFabric.mjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n fitZoom: s.fitZoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: (manualZoom = 1) => {\n const { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const combinedZoom = manualZoom * fitZoom\n if (canvas) {\n // 先重置 viewport transform\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n const deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n const deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, deltaX, deltaY])\n } else {\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n }\n canvas.requestRenderAll()\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n }\n }, [store])\n\n return useMemo(\n () => ({\n ...generalHelper,\n ...state,\n }),\n [generalHelper, state],\n )\n}\n"],"names":["selector","s","useReactFabric","store","useStoreApi","state","useStore","shallow","generalHelper","useMemo","n","manualZoom","canvas","fitZoom","maxManualZoom","minManualZoom","combinedZoom","center","defaultCentered","bgWidth","bgHeight","deltaX","deltaY"],"mappings":"0JAKA,MAAMA,EAAYC,IAAyB,CACzC,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,WAAYA,EAAE,WACd,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,OAAQA,EAAE,OACV,aAAcA,EAAE,aAChB,cAAeA,EAAE,cACjB,SAAUA,EAAE,SACZ,SAAUA,EAAE,SACZ,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,YAAaA,EAAE,YACf,MAAOA,EAAE,MACT,KAAMA,EAAE,KACR,QAASA,EAAE,QACX,gBAAiBA,EAAE,gBACnB,WAAYA,EAAE,WACd,cAAeA,EAAE,cACjB,cAAeA,EAAE,cACjB,QAASA,EAAE,OACb,YAEgBC,GAAiB,CAC/B,MAAMC,EAAQC,EAAAA,EACRC,EAAQC,EAASN,EAAUO,CAAO,EAElCC,EAAgBC,EAAQ,KACrB,CACL,UAAW,IAAMN,EAAM,WAAW,OAClC,SAAU,IAAMA,EAAM,SAAA,EAAW,MAAM,IAAIO,IAAM,CAAE,GAAGA,CAAE,EAAE,EAC1D,SAAU,IAAMP,EAAM,SAKtB,OAAQ,IAAM,CACZ,GAAI,CAAE,WAAAQ,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EAKA,QAAS,IAAM,CACb,GAAI,CAAE,WAAAL,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,WAAW,KAKhC,cAAe,CAACQ,EAAa,IAAM,CACjC,KAAM,CAAE,OAAAC,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAS,EAE1Da,EAAeL,EAAaE,EAClC,GAAID,EAAQ,CAEV,GAAIM,GAAmBN,EAAO,gBAAiB,CAC7C,MAAMO,EAAUP,EAAO,gBAAgB,OAAS,EAC1CQ,EAAWR,EAAO,gBAAgB,QAAU,EAC5CS,GAAUT,EAAO,MAASO,EAAUH,GAAgB,EACpDM,GAAUV,EAAO,OAAUQ,EAAWJ,GAAgB,EAC5DJ,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAcK,EAAQC,CAAM,CAAC,CAChF,MACEV,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAEtEJ,EAAO,kBACT,CAEAT,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,CACF,GACC,CAACb,CAAK,CAAC,EAEV,OAAOM,EACL,KAAO,CACL,GAAGD,EACH,GAAGH,CACL,GACA,CAACG,EAAeH,CAAK,CACvB,CACF"}
@@ -1,2 +1,2 @@
1
- "use client";import{default as o}from"./container/ReactFabric/index.mjs";import{useReactFabric as a}from"./hooks/useReactFabric.mjs";import{useZoom as l}from"./hooks/useZoom.mjs";import{default as x}from"./components/BackgroundImage/index.mjs";import{default as s}from"./components/Canvas/index.mjs";import{default as d}from"./components/Group/index.mjs";import{default as n}from"./components/NodeToolbarPortal/index.mjs";import{ReactFabricProvider as P}from"./components/ReactFabricProvider.mjs";import{default as b}from"./components/Rect/index.mjs";import{default as R}from"./components/Control/index.mjs";import{default as v}from"./components/Image/index.mjs";import{default as I}from"./components/Control2/index.mjs";import{default as G}from"./components/Text/index.mjs";import{default as j}from"./components/Path/index.mjs";import{default as w}from"./components/Line/index.mjs";import{default as B}from"./components/Ellipse/index.mjs";import{default as E}from"./components/IText/index.mjs";import{default as O}from"./components/Textbox/index.mjs";import{default as Z}from"./components/WavyLine/index.mjs";import{default as z}from"./components/Objects/index.mjs";import{default as H}from"./plugins/FreeRect.mjs";import{default as K}from"./plugins/GridLine.mjs";import{default as Q}from"./plugins/Pinch.mjs";import{default as U}from"./plugins/FreeDraw.mjs";import{default as X}from"./plugins/FreeText.mjs";export{x as BackgroundImage,s as Canvas,R as Control,I as Control2,B as Ellipse,d as Group,E as IText,v as Image,w as Line,n as NodeToolbarPortal,z as Objects,j as Path,U as PluginFreeDraw,H as PluginFreeRect,X as PluginFreeText,K as PluginGrid,Q as PluginPinch,o as ReactFabric,P as ReactFabricProvider,b as Rect,G as Text,O as Textbox,Z as WavyLine,a as useReactFabric,l as useZoom};
1
+ "use client";import{default as o}from"./container/ReactFabric/index.mjs";import{useReactFabric as a}from"./hooks/useReactFabric.mjs";import{useZoom as l}from"./hooks/useZoom.mjs";import{useStore as s,useStoreApi as x}from"./hooks/useStore.mjs";import{default as p}from"./components/BackgroundImage/index.mjs";import{default as i}from"./components/Canvas/index.mjs";import{default as c}from"./components/Group/index.mjs";import{default as g}from"./components/NodeToolbarPortal/index.mjs";import{ReactFabricProvider as F}from"./components/ReactFabricProvider.mjs";import{default as T}from"./components/Rect/index.mjs";import{default as C}from"./components/Control/index.mjs";import{default as h}from"./components/Image/index.mjs";import{default as y}from"./components/Control2/index.mjs";import{default as L}from"./components/Text/index.mjs";import{default as j}from"./components/Path/index.mjs";import{default as A}from"./components/Line/index.mjs";import{default as D}from"./components/Ellipse/index.mjs";import{default as M}from"./components/IText/index.mjs";import{default as O}from"./components/Textbox/index.mjs";import{default as Z}from"./components/Polyline/index.mjs";import{default as z}from"./components/WavyLine/index.mjs";import{default as J}from"./components/Objects/index.mjs";import{default as Q}from"./plugins/FreeRect.mjs";import{default as V}from"./plugins/GridLine.mjs";import{default as Y}from"./plugins/Pinch.mjs";import{default as $}from"./plugins/FreeDraw.mjs";import{default as re}from"./plugins/FreeText.mjs";import{default as te}from"./plugins/Mask.mjs";export{p as BackgroundImage,i as Canvas,C as Control,y as Control2,D as Ellipse,c as Group,M as IText,h as Image,A as Line,g as NodeToolbarPortal,J as Objects,j as Path,$ as PluginFreeDraw,Q as PluginFreeRect,re as PluginFreeText,V as PluginGrid,te as PluginMask,Y as PluginPinch,Z as Polyline,o as ReactFabric,F as ReactFabricProvider,T as Rect,L as Text,O as Textbox,z as WavyLine,a as useReactFabric,s as useStore,x as useStoreApi,l as useZoom};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,2 @@
1
+ "use client";import{jsx as h,Fragment as m}from"react/jsx-runtime";import{Rect as f}from"fabric";import{useRef as p,useEffect as a}from"react";import{useStoreApi as b}from"../hooks/useStore.mjs";const k=i=>{const{defaultFill:d=!1,fullness:c=!1}=i,l=b(),{canvas:e}=l.getState(),t=p(null),u=()=>new f({left:0,top:0,fill:"rgba(0,0,0,0.2)",selectable:!1,evented:!1,excludeFromExport:!0,isMask:!0}),o=()=>{e?.backgroundImage&&(t.current?(t.current.set({clipPath:null}),e.requestRenderAll()):(t.current=u(),t.current.set({width:e.backgroundImage?.width,height:e.backgroundImage?.height}),e.add(t.current),e.moveObjectTo(t.current,-999)))};return a(()=>{c&&o()},[c]),a(()=>{if(!e)return;d&&o();const n=s=>{const{selected:g}=s,r=g[0];!e||!r||r.get("showMark")&&(r.inverted=!0,r.absolutePositioned=!0,t.current?(t.current.set({width:e.backgroundImage?.width||t.current.width,height:e.backgroundImage?.height||t.current.height,clipPath:r}),e.requestRenderAll()):(t.current=u(),setTimeout(()=>{t.current&&(t.current.set({width:e.backgroundImage?.width,height:e.backgroundImage?.height,clipPath:r}),e.add(t.current),e.moveObjectTo(t.current,-999))},100)))};return e.on("selection:created",n),e.on("selection:updated",n),()=>{t.current&&(e.remove(t.current),t.current=null),e.off("selection:created",n),e.off("selection:updated",n),e.requestRenderAll()}},[e]),h(m,{})};export{k as default};
2
+ //# sourceMappingURL=Mask.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mask.mjs","sources":["../../../src/plugins/Mask.tsx"],"sourcesContent":["import { Rect } from 'fabric'\nimport { useEffect, useRef } from 'react'\nimport { useStoreApi } from '../hooks/useStore'\n\nexport type PluginMaskProps = {\n defaultFill?: boolean // 是否默认没有选择对象时,蒙层遮住整个图片\n fullness?: boolean // 是否完全遮住\n}\n\n/** 聚焦对象时蒙层;边界是背景图片 */\nconst PluginMask = (props: PluginMaskProps) => {\n const { defaultFill = false, fullness = false } = props\n const store = useStoreApi()\n const { canvas } = store.getState()\n const maskRectRef = useRef<Rect | null>(null)\n\n const initMaskRect = () => {\n return new Rect({\n left: 0,\n top: 0,\n fill: 'rgba(0,0,0,0.2)' /** 半透明灰色 */,\n selectable: false,\n evented: false,\n excludeFromExport: true /** toJSON 不存在,getObjects 存在 */,\n isMask: true,\n })\n }\n\n const renderDefaultMask = () => {\n if (!canvas?.backgroundImage) return\n\n if (maskRectRef.current) {\n maskRectRef.current.set({\n clipPath: null,\n })\n canvas.requestRenderAll()\n } else {\n maskRectRef.current = initMaskRect()\n maskRectRef.current.set({\n width: canvas.backgroundImage?.width,\n height: canvas.backgroundImage?.height,\n })\n canvas.add(maskRectRef.current)\n canvas.moveObjectTo(maskRectRef.current, -999)\n }\n }\n\n useEffect(() => {\n if (fullness) renderDefaultMask()\n }, [fullness])\n\n useEffect(() => {\n if (!canvas) return\n if (defaultFill) renderDefaultMask()\n\n const renderMask = (e: any) => {\n const { selected } = e\n const target = selected[0]\n if (!canvas || !target) return\n if (!target.get('showMark')) return\n\n /** 必须加上以下参数,才能裁切成功 */\n target.inverted = true\n target.absolutePositioned = true\n /** 从未触发过时,初始化蒙层 */\n if (!maskRectRef.current) {\n maskRectRef.current = initMaskRect()\n setTimeout(() => {\n if (!maskRectRef.current) return\n maskRectRef.current.set({\n width: canvas.backgroundImage?.width,\n height: canvas.backgroundImage?.height,\n clipPath: target,\n })\n canvas.add(maskRectRef.current)\n canvas.moveObjectTo(maskRectRef.current, -999)\n }, 100)\n } else {\n maskRectRef.current.set({\n width: canvas.backgroundImage?.width || maskRectRef.current.width,\n height: canvas.backgroundImage?.height || maskRectRef.current.height,\n clipPath: target,\n })\n canvas.requestRenderAll()\n }\n }\n\n /** 第一次是点击触发 created,切换另一个框是触发 updated */\n canvas.on('selection:created', renderMask)\n canvas.on('selection:updated', renderMask)\n\n return () => {\n if (maskRectRef.current) {\n canvas.remove(maskRectRef.current)\n maskRectRef.current = null\n }\n canvas.off('selection:created', renderMask)\n canvas.off('selection:updated', renderMask)\n canvas.requestRenderAll()\n }\n }, [canvas])\n\n return <></>\n}\n\nexport default PluginMask\n"],"names":["PluginMask","props","defaultFill","fullness","store","useStoreApi","canvas","maskRectRef","useRef","initMaskRect","Rect","renderDefaultMask","useEffect","renderMask","e","selected","target","jsx","Fragment"],"mappings":"mMAUA,MAAMA,EAAcC,GAA2B,CAC3C,KAAM,CAAE,YAAAC,EAAc,GAAO,SAAAC,EAAW,EAAM,EAAIF,EAC5CG,EAAQC,EAAY,EACpB,CAAE,OAAAC,CAAO,EAAIF,EAAM,SACnBG,EAAAA,EAAcC,EAAoB,IAAI,EAEtCC,EAAe,IACV,IAAIC,EAAK,CACZ,KAAM,EACN,IAAK,EACL,KAAM,kBACN,WAAY,GACZ,QAAS,GACT,kBAAmB,GACnB,OAAQ,EACZ,CAAC,EAGCC,EAAoB,IAAM,CACvBL,GAAQ,kBAETC,EAAY,SACZA,EAAY,QAAQ,IAAI,CACpB,SAAU,IACd,CAAC,EACDD,EAAO,iBAAiB,IAExBC,EAAY,QAAUE,EAAa,EACnCF,EAAY,QAAQ,IAAI,CACpB,MAAOD,EAAO,iBAAiB,MAC/B,OAAQA,EAAO,iBAAiB,MACpC,CAAC,EACDA,EAAO,IAAIC,EAAY,OAAO,EAC9BD,EAAO,aAAaC,EAAY,QAAS,IAAI,GAErD,EAEA,OAAAK,EAAU,IAAM,CACRT,GAAUQ,EAAAA,CAClB,EAAG,CAACR,CAAQ,CAAC,EAEbS,EAAU,IAAM,CACZ,GAAI,CAACN,EAAQ,OACTJ,GAAaS,IAEjB,MAAME,EAAcC,GAAW,CAC3B,KAAM,CAAE,SAAAC,CAAS,EAAID,EACfE,EAASD,EAAS,CAAC,EACrB,CAACT,GAAU,CAACU,GACXA,EAAO,IAAI,UAAU,IAG1BA,EAAO,SAAW,GAClBA,EAAO,mBAAqB,GAEvBT,EAAY,SAabA,EAAY,QAAQ,IAAI,CACpB,MAAOD,EAAO,iBAAiB,OAASC,EAAY,QAAQ,MAC5D,OAAQD,EAAO,iBAAiB,QAAUC,EAAY,QAAQ,OAC9D,SAAUS,CACd,CAAC,EACDV,EAAO,iBAAiB,IAjBxBC,EAAY,QAAUE,EAAa,EACnC,WAAW,IAAM,CACRF,EAAY,UACjBA,EAAY,QAAQ,IAAI,CACpB,MAAOD,EAAO,iBAAiB,MAC/B,OAAQA,EAAO,iBAAiB,OAChC,SAAUU,CACd,CAAC,EACDV,EAAO,IAAIC,EAAY,OAAO,EAC9BD,EAAO,aAAaC,EAAY,QAAS,IAAI,EACjD,EAAG,GAAG,GASd,EAGA,OAAAD,EAAO,GAAG,oBAAqBO,CAAU,EACzCP,EAAO,GAAG,oBAAqBO,CAAU,EAElC,IAAM,CACLN,EAAY,UACZD,EAAO,OAAOC,EAAY,OAAO,EACjCA,EAAY,QAAU,MAE1BD,EAAO,IAAI,oBAAqBO,CAAU,EAC1CP,EAAO,IAAI,oBAAqBO,CAAU,EAC1CP,EAAO,iBAAA,CACX,CACJ,EAAG,CAACA,CAAM,CAAC,EAEJW,EAAAC,EAAA,CAAA,CAAE,CACb"}
@@ -8,5 +8,5 @@ import type { FabricObject } from 'fabric';
8
8
  * @param children 需要处理的子元素
9
9
  * @returns 处理后的 children
10
10
  */
11
- export declare function useInstancePosition(instance: FabricObject | undefined, children: ReactNode): string | number | boolean | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined;
11
+ export declare function useInstancePosition(instance: FabricObject | undefined, children: ReactNode): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
12
12
  //# sourceMappingURL=useInstancePosition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useInstancePosition.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInstancePosition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAG1C;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,+JAoE1F"}
1
+ {"version":3,"file":"useInstancePosition.d.ts","sourceRoot":"","sources":["../../../src/hooks/useInstancePosition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAG1C;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,qGAoE1F"}
@@ -15,6 +15,7 @@ export declare function useReactFabric(): {
15
15
  setZoomable: (enable: boolean) => void;
16
16
  scale: number;
17
17
  zoom: number;
18
+ fitZoom: number;
18
19
  defaultCentered: boolean | undefined;
19
20
  manualZoom: number;
20
21
  maxManualZoom: number;
@@ -1 +1 @@
1
- {"version":3,"file":"useReactFabric.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReactFabric.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AA0BtD,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUxB;;OAEG;;IAuBH;;OAEG;;;IAwBH;;OAEG;;EAkCR"}
1
+ {"version":3,"file":"useReactFabric.d.ts","sourceRoot":"","sources":["../../../src/hooks/useReactFabric.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AA2BtD,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUxB;;OAEG;;IAuBH;;OAEG;;;IAwBH;;OAEG;;EAkCR"}
@@ -2,6 +2,7 @@ export { default as ReactFabric } from './container/ReactFabric';
2
2
  export type { ReactFabricProps } from './container/ReactFabric';
3
3
  export { useReactFabric } from './hooks/useReactFabric';
4
4
  export { useZoom } from './hooks/useZoom';
5
+ export { useStore, useStoreApi } from './hooks/useStore';
5
6
  export { default as BackgroundImage } from './components/BackgroundImage';
6
7
  export { default as Canvas } from './components/Canvas';
7
8
  export { default as Group } from './components/Group';
@@ -28,6 +29,8 @@ export { default as IText } from './components/IText';
28
29
  export type { ITextProps } from './components/IText';
29
30
  export { default as Textbox } from './components/Textbox';
30
31
  export type { TextboxProps } from './components/Textbox';
32
+ export { default as Polyline } from './components/Polyline';
33
+ export type { PolylineProps } from './components/Polyline';
31
34
  export { default as WavyLine } from './components/WavyLine';
32
35
  export type { WavyLineProps } from './components/WavyLine';
33
36
  export { default as Objects } from './components/Objects';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAIzC,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,YAAY,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AAEhF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,cAAc,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,YAAY,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AAEhF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnD,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,cAAc,WAAW,CAAA"}
@@ -4,4 +4,5 @@ export type { FreeRectProps } from './FreeRect';
4
4
  export { default as PluginPinch } from './Pinch';
5
5
  export { default as PluginFreeDraw } from './FreeDraw';
6
6
  export { default as PluginFreeText } from './FreeText';
7
+ export { default as PluginMask } from './Mask';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cs-open/react-fabric",
3
3
  "type": "module",
4
- "version": "0.0.8",
4
+ "version": "0.0.12",
5
5
  "description": "React Fabric",
6
6
  "keywords": [
7
7
  "@cs-open/react-fabric",
@@ -73,7 +73,7 @@
73
73
  "autoprefixer": "^10.4.15",
74
74
  "cssnano": "^6.0.1",
75
75
  "eslint": "^9.16.0",
76
- "fabric": "^6.6.4",
76
+ "fabric": "latest",
77
77
  "hammerjs": "^2.0.0",
78
78
  "postcss": "^8.4.21",
79
79
  "postcss-cli": "^11.0.0",
@@ -88,9 +88,9 @@
88
88
  "typescript-eslint": "^8.17.0",
89
89
  "use-sync-external-store": "^1.4.0",
90
90
  "zustand": "^4.0.0 || ^5.0.0",
91
- "@cs-open/rollup-config": "0.0.6",
92
- "@cs-open/eslint-config": "0.0.6",
93
- "@cs-open/tsconfig": "0.0.6"
91
+ "@cs-open/tsconfig": "0.0.9",
92
+ "@cs-open/rollup-config": "0.0.9",
93
+ "@cs-open/eslint-config": "0.0.9"
94
94
  },
95
95
  "dependencies": {
96
96
  "es-toolkit": "^1.39.10",