@cs-open/react-fabric 0.0.3
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 +21 -0
- package/dist/cjs/components/BackgroundImage/index.cjs +2 -0
- package/dist/cjs/components/BackgroundImage/index.cjs.map +1 -0
- package/dist/cjs/components/Canvas/index.cjs +2 -0
- package/dist/cjs/components/Canvas/index.cjs.map +1 -0
- package/dist/cjs/components/Control/index.cjs +2 -0
- package/dist/cjs/components/Control/index.cjs.map +1 -0
- package/dist/cjs/components/Ellipse/index.cjs +2 -0
- package/dist/cjs/components/Ellipse/index.cjs.map +1 -0
- package/dist/cjs/components/Group/index.cjs +2 -0
- package/dist/cjs/components/Group/index.cjs.map +1 -0
- package/dist/cjs/components/Image/index.cjs +2 -0
- package/dist/cjs/components/Image/index.cjs.map +1 -0
- package/dist/cjs/components/Line/index.cjs +2 -0
- package/dist/cjs/components/Line/index.cjs.map +1 -0
- package/dist/cjs/components/Loading/index.cjs +2 -0
- package/dist/cjs/components/Loading/index.cjs.map +1 -0
- package/dist/cjs/components/NodeToolbarPortal/index.cjs +2 -0
- package/dist/cjs/components/NodeToolbarPortal/index.cjs.map +1 -0
- package/dist/cjs/components/Objects/index.cjs +2 -0
- package/dist/cjs/components/Objects/index.cjs.map +1 -0
- package/dist/cjs/components/Path/index.cjs +2 -0
- package/dist/cjs/components/Path/index.cjs.map +1 -0
- package/dist/cjs/components/ReactFabricProvider.cjs +2 -0
- package/dist/cjs/components/ReactFabricProvider.cjs.map +1 -0
- package/dist/cjs/components/Rect/index.cjs +2 -0
- package/dist/cjs/components/Rect/index.cjs.map +1 -0
- package/dist/cjs/components/StoreUpdater/index.cjs +2 -0
- package/dist/cjs/components/StoreUpdater/index.cjs.map +1 -0
- package/dist/cjs/components/Text/index.cjs +2 -0
- package/dist/cjs/components/Text/index.cjs.map +1 -0
- package/dist/cjs/constants.cjs +2 -0
- package/dist/cjs/constants.cjs.map +1 -0
- package/dist/cjs/container/ReactFabric/Wrapper.cjs +2 -0
- package/dist/cjs/container/ReactFabric/Wrapper.cjs.map +1 -0
- package/dist/cjs/container/ReactFabric/index.cjs +2 -0
- package/dist/cjs/container/ReactFabric/index.cjs.map +1 -0
- package/dist/cjs/contexts/StoreContext.cjs +2 -0
- package/dist/cjs/contexts/StoreContext.cjs.map +1 -0
- package/dist/cjs/hooks/useCreateObject.cjs +2 -0
- package/dist/cjs/hooks/useCreateObject.cjs.map +1 -0
- package/dist/cjs/hooks/useDidUpdate.cjs +2 -0
- package/dist/cjs/hooks/useDidUpdate.cjs.map +1 -0
- package/dist/cjs/hooks/useDraggable.cjs +2 -0
- package/dist/cjs/hooks/useDraggable.cjs.map +1 -0
- package/dist/cjs/hooks/useReactFabric.cjs +2 -0
- package/dist/cjs/hooks/useReactFabric.cjs.map +1 -0
- package/dist/cjs/hooks/useResizeHandler.cjs +2 -0
- package/dist/cjs/hooks/useResizeHandler.cjs.map +1 -0
- package/dist/cjs/hooks/useSplitProps.cjs +2 -0
- package/dist/cjs/hooks/useSplitProps.cjs.map +1 -0
- package/dist/cjs/hooks/useStore.cjs +2 -0
- package/dist/cjs/hooks/useStore.cjs.map +1 -0
- package/dist/cjs/hooks/useZoom.cjs +2 -0
- package/dist/cjs/hooks/useZoom.cjs.map +1 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/plugins/FreeRect.cjs +2 -0
- package/dist/cjs/plugins/FreeRect.cjs.map +1 -0
- package/dist/cjs/plugins/GridLine.cjs +5 -0
- package/dist/cjs/plugins/GridLine.cjs.map +1 -0
- package/dist/cjs/plugins/Pinch.cjs +2 -0
- package/dist/cjs/plugins/Pinch.cjs.map +1 -0
- package/dist/cjs/store/index.cjs +2 -0
- package/dist/cjs/store/index.cjs.map +1 -0
- package/dist/cjs/store/initialState.cjs +2 -0
- package/dist/cjs/store/initialState.cjs.map +1 -0
- package/dist/cjs/toolbar/Vertical/index.cjs +2 -0
- package/dist/cjs/toolbar/Vertical/index.cjs.map +1 -0
- package/dist/cjs/types/canvas.cjs +2 -0
- package/dist/cjs/types/canvas.cjs.map +1 -0
- package/dist/cjs/types/component-props.cjs +2 -0
- package/dist/cjs/types/component-props.cjs.map +1 -0
- package/dist/cjs/types/general.cjs +2 -0
- package/dist/cjs/types/general.cjs.map +1 -0
- package/dist/cjs/types/nodes.cjs +2 -0
- package/dist/cjs/types/nodes.cjs.map +1 -0
- package/dist/cjs/types/object.cjs +2 -0
- package/dist/cjs/types/object.cjs.map +1 -0
- package/dist/cjs/types/store.cjs +2 -0
- package/dist/cjs/types/store.cjs.map +1 -0
- package/dist/cjs/types/utils.cjs +2 -0
- package/dist/cjs/types/utils.cjs.map +1 -0
- package/dist/cjs/utils/constants.cjs +2 -0
- package/dist/cjs/utils/constants.cjs.map +1 -0
- package/dist/cjs/utils/dom.cjs +2 -0
- package/dist/cjs/utils/dom.cjs.map +1 -0
- package/dist/cjs/utils/events.cjs +2 -0
- package/dist/cjs/utils/events.cjs.map +1 -0
- package/dist/cjs/utils/position.cjs +2 -0
- package/dist/cjs/utils/position.cjs.map +1 -0
- package/dist/cjs/utils/props.cjs +2 -0
- package/dist/cjs/utils/props.cjs.map +1 -0
- package/dist/esm/components/BackgroundImage/index.mjs +2 -0
- package/dist/esm/components/BackgroundImage/index.mjs.map +1 -0
- package/dist/esm/components/Canvas/index.mjs +2 -0
- package/dist/esm/components/Canvas/index.mjs.map +1 -0
- package/dist/esm/components/Control/index.mjs +2 -0
- package/dist/esm/components/Control/index.mjs.map +1 -0
- package/dist/esm/components/Ellipse/index.mjs +2 -0
- package/dist/esm/components/Ellipse/index.mjs.map +1 -0
- package/dist/esm/components/Group/index.mjs +2 -0
- package/dist/esm/components/Group/index.mjs.map +1 -0
- package/dist/esm/components/Line/index.mjs +2 -0
- package/dist/esm/components/Line/index.mjs.map +1 -0
- package/dist/esm/components/Loading/index.mjs +2 -0
- package/dist/esm/components/Loading/index.mjs.map +1 -0
- package/dist/esm/components/NodeToolbarPortal/index.mjs +2 -0
- package/dist/esm/components/NodeToolbarPortal/index.mjs.map +1 -0
- package/dist/esm/components/Objects/index.mjs +2 -0
- package/dist/esm/components/Objects/index.mjs.map +1 -0
- package/dist/esm/components/Path/index.mjs +2 -0
- package/dist/esm/components/Path/index.mjs.map +1 -0
- package/dist/esm/components/ReactFabricProvider.mjs +2 -0
- package/dist/esm/components/ReactFabricProvider.mjs.map +1 -0
- package/dist/esm/components/Rect/index.mjs +2 -0
- package/dist/esm/components/Rect/index.mjs.map +1 -0
- package/dist/esm/components/StoreUpdater/index.mjs +2 -0
- package/dist/esm/components/StoreUpdater/index.mjs.map +1 -0
- package/dist/esm/components/Text/index.mjs +2 -0
- package/dist/esm/components/Text/index.mjs.map +1 -0
- package/dist/esm/container/ReactFabric/Wrapper.mjs +2 -0
- package/dist/esm/container/ReactFabric/Wrapper.mjs.map +1 -0
- package/dist/esm/container/ReactFabric/index.mjs +2 -0
- package/dist/esm/container/ReactFabric/index.mjs.map +1 -0
- package/dist/esm/contexts/StoreContext.mjs +2 -0
- package/dist/esm/contexts/StoreContext.mjs.map +1 -0
- package/dist/esm/hooks/useCreateObject.mjs +2 -0
- package/dist/esm/hooks/useCreateObject.mjs.map +1 -0
- package/dist/esm/hooks/useDidUpdate.mjs +2 -0
- package/dist/esm/hooks/useDidUpdate.mjs.map +1 -0
- package/dist/esm/hooks/useDraggable.mjs +2 -0
- package/dist/esm/hooks/useDraggable.mjs.map +1 -0
- package/dist/esm/hooks/useReactFabric.mjs +2 -0
- package/dist/esm/hooks/useReactFabric.mjs.map +1 -0
- package/dist/esm/hooks/useResizeHandler.mjs +2 -0
- package/dist/esm/hooks/useResizeHandler.mjs.map +1 -0
- package/dist/esm/hooks/useSplitProps.mjs +2 -0
- package/dist/esm/hooks/useSplitProps.mjs.map +1 -0
- package/dist/esm/hooks/useStore.mjs +2 -0
- package/dist/esm/hooks/useStore.mjs.map +1 -0
- package/dist/esm/hooks/useZoom.mjs +2 -0
- package/dist/esm/hooks/useZoom.mjs.map +1 -0
- package/dist/esm/index.mjs +2 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/plugins/FreeRect.mjs +2 -0
- package/dist/esm/plugins/FreeRect.mjs.map +1 -0
- package/dist/esm/plugins/GridLine.mjs +5 -0
- package/dist/esm/plugins/GridLine.mjs.map +1 -0
- package/dist/esm/plugins/Pinch.mjs +2 -0
- package/dist/esm/plugins/Pinch.mjs.map +1 -0
- package/dist/esm/store/index.mjs +2 -0
- package/dist/esm/store/index.mjs.map +1 -0
- package/dist/esm/store/initialState.mjs +2 -0
- package/dist/esm/store/initialState.mjs.map +1 -0
- package/dist/esm/toolbar/Vertical/index.mjs +2 -0
- package/dist/esm/toolbar/Vertical/index.mjs.map +1 -0
- package/dist/esm/utils/constants.mjs +2 -0
- package/dist/esm/utils/constants.mjs.map +1 -0
- package/dist/esm/utils/events.mjs +2 -0
- package/dist/esm/utils/events.mjs.map +1 -0
- package/dist/esm/utils/props.mjs +2 -0
- package/dist/esm/utils/props.mjs.map +1 -0
- package/dist/types/components/BackgroundImage/index.d.ts +19 -0
- package/dist/types/components/BackgroundImage/index.d.ts.map +1 -0
- package/dist/types/components/Canvas/index.d.ts +11 -0
- package/dist/types/components/Canvas/index.d.ts.map +1 -0
- package/dist/types/components/Control/index.d.ts +28 -0
- package/dist/types/components/Control/index.d.ts.map +1 -0
- package/dist/types/components/Ellipse/index.d.ts +19 -0
- package/dist/types/components/Ellipse/index.d.ts.map +1 -0
- package/dist/types/components/Group/index.d.ts +24 -0
- package/dist/types/components/Group/index.d.ts.map +1 -0
- package/dist/types/components/Image/index.d.ts +18 -0
- package/dist/types/components/Image/index.d.ts.map +1 -0
- package/dist/types/components/Line/index.d.ts +11 -0
- package/dist/types/components/Line/index.d.ts.map +1 -0
- package/dist/types/components/Loading/index.d.ts +3 -0
- package/dist/types/components/Loading/index.d.ts.map +1 -0
- package/dist/types/components/NodeToolbarPortal/index.d.ts +9 -0
- package/dist/types/components/NodeToolbarPortal/index.d.ts.map +1 -0
- package/dist/types/components/Objects/index.d.ts +9 -0
- package/dist/types/components/Objects/index.d.ts.map +1 -0
- package/dist/types/components/Path/index.d.ts +11 -0
- package/dist/types/components/Path/index.d.ts.map +1 -0
- package/dist/types/components/ReactFabricProvider.d.ts +11 -0
- package/dist/types/components/ReactFabricProvider.d.ts.map +1 -0
- package/dist/types/components/Rect/index.d.ts +20 -0
- package/dist/types/components/Rect/index.d.ts.map +1 -0
- package/dist/types/components/StoreUpdater/index.d.ts +8 -0
- package/dist/types/components/StoreUpdater/index.d.ts.map +1 -0
- package/dist/types/components/Text/index.d.ts +11 -0
- package/dist/types/components/Text/index.d.ts.map +1 -0
- package/dist/types/constants.d.ts +5 -0
- package/dist/types/constants.d.ts.map +1 -0
- package/dist/types/container/ReactFabric/Wrapper.d.ts +10 -0
- package/dist/types/container/ReactFabric/Wrapper.d.ts.map +1 -0
- package/dist/types/container/ReactFabric/index.d.ts +69 -0
- package/dist/types/container/ReactFabric/index.d.ts.map +1 -0
- package/dist/types/contexts/StoreContext.d.ts +4 -0
- package/dist/types/contexts/StoreContext.d.ts.map +1 -0
- package/dist/types/hooks/useCreateObject.d.ts +15 -0
- package/dist/types/hooks/useCreateObject.d.ts.map +1 -0
- package/dist/types/hooks/useDidUpdate.d.ts +9 -0
- package/dist/types/hooks/useDidUpdate.d.ts.map +1 -0
- package/dist/types/hooks/useDraggable.d.ts +3 -0
- package/dist/types/hooks/useDraggable.d.ts.map +1 -0
- package/dist/types/hooks/useReactFabric.d.ts +55 -0
- package/dist/types/hooks/useReactFabric.d.ts.map +1 -0
- package/dist/types/hooks/useResizeHandler.d.ts +3 -0
- package/dist/types/hooks/useResizeHandler.d.ts.map +1 -0
- package/dist/types/hooks/useSplitProps.d.ts +15 -0
- package/dist/types/hooks/useSplitProps.d.ts.map +1 -0
- package/dist/types/hooks/useStore.d.ts +13 -0
- package/dist/types/hooks/useStore.d.ts.map +1 -0
- package/dist/types/hooks/useZoom.d.ts +2 -0
- package/dist/types/hooks/useZoom.d.ts.map +1 -0
- package/dist/types/index.d.ts +29 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/plugins/FreeRect.d.ts +15 -0
- package/dist/types/plugins/FreeRect.d.ts.map +1 -0
- package/dist/types/plugins/GridLine.d.ts +7 -0
- package/dist/types/plugins/GridLine.d.ts.map +1 -0
- package/dist/types/plugins/Pinch.d.ts +8 -0
- package/dist/types/plugins/Pinch.d.ts.map +1 -0
- package/dist/types/store/index.d.ts +10 -0
- package/dist/types/store/index.d.ts.map +1 -0
- package/dist/types/store/initialState.d.ts +12 -0
- package/dist/types/store/initialState.d.ts.map +1 -0
- package/dist/types/toolbar/Vertical/index.d.ts +10 -0
- package/dist/types/toolbar/Vertical/index.d.ts.map +1 -0
- package/dist/types/types/canvas.d.ts +15 -0
- package/dist/types/types/canvas.d.ts.map +1 -0
- package/dist/types/types/component-props.d.ts +41 -0
- package/dist/types/types/component-props.d.ts.map +1 -0
- package/dist/types/types/general.d.ts +2 -0
- package/dist/types/types/general.d.ts.map +1 -0
- package/dist/types/types/nodes.d.ts +91 -0
- package/dist/types/types/nodes.d.ts.map +1 -0
- package/dist/types/types/object.d.ts +22 -0
- package/dist/types/types/object.d.ts.map +1 -0
- package/dist/types/types/store.d.ts +59 -0
- package/dist/types/types/store.d.ts.map +1 -0
- package/dist/types/types/utils.d.ts +6 -0
- package/dist/types/types/utils.d.ts.map +1 -0
- package/dist/types/utils/constants.d.ts +5 -0
- package/dist/types/utils/constants.d.ts.map +1 -0
- package/dist/types/utils/dom.d.ts +3 -0
- package/dist/types/utils/dom.d.ts.map +1 -0
- package/dist/types/utils/events.d.ts +5 -0
- package/dist/types/utils/events.d.ts.map +1 -0
- package/dist/types/utils/position.d.ts +9 -0
- package/dist/types/utils/position.d.ts.map +1 -0
- package/dist/types/utils/props.d.ts +4 -0
- package/dist/types/utils/props.d.ts.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var c=require("zustand/traditional"),l=require("./initialState.cjs");const h=({nodes:n,defaultNodes:r,width:u,height:g})=>c.createWithEqualityFn((a,o)=>({...l.default({nodes:n,width:u,height:g,defaultNodes:r}),setDimensions:e=>{const{width:t,height:d}=e,s=o(),i={width:t??s.width,height:d??s.height};o().canvas?.setDimensions(i),a(i)},setLoading:e=>{a({loading:e})},setDraggable:e=>{a({draggable:e});const t=o().canvas;t&&(t.setCursor(e?"grab":"default"),t.hoverCursor=e?"grab":"default",t.requestRenderAll())},setZoomable:e=>{a({zoomable:e})},setIsDragging:e=>{a({isDragging:e})},setSelection:e=>{const t=o().canvas;t&&(a({selection:e}),t.set("selection",e),t.requestRenderAll())},setDefaultDraggable:e=>{if(e===void 0)return;const{setDraggable:t}=o();a({hasDefaultDraggable:!0}),t(e)},setDefaultSelection:e=>{if(e===void 0)return;const{setSelection:t}=o();a({hasDefaultSelection:!0}),t(e)},setFitZoom:e=>{a({fitZoom:e})},setManualZoom:e=>{a({manualZoom:e})},setMinManualZoom:e=>{a({minManualZoom:e})},setZoom:e=>{a({zoom:e})},setMaxManualZoom:e=>{a({maxManualZoom:e})},reset:()=>a({...l.default()})}),Object.is);exports.createStore=h;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/store/index.ts"],"sourcesContent":["import { createWithEqualityFn } from 'zustand/traditional'\nimport type { Node } from '../types/nodes'\nimport type { ReactFabricState } from '../types/store'\nimport getInitialState from './initialState'\n\nconst createStore = ({\n nodes,\n defaultNodes,\n width,\n height,\n}: {\n nodes?: Node[]\n defaultNodes?: Node[]\n width?: number\n height?: number\n}) =>\n createWithEqualityFn<ReactFabricState>(\n (set, get) => ({\n ...getInitialState({ nodes, width, height, defaultNodes }),\n setDimensions: (options: { width?: number; height?: number }) => {\n const { width, height } = options\n const currentState = get()\n\n // 合并现有尺寸和新尺寸\n const newDimensions = {\n width: width ?? currentState.width,\n height: height ?? currentState.height,\n }\n\n get().canvas?.setDimensions(newDimensions)\n set(newDimensions)\n },\n setLoading: loading => {\n set({ loading })\n },\n setDraggable: draggable => {\n set({ draggable })\n const canvas = get().canvas\n // TODO 无效\n if (canvas) {\n canvas.setCursor(draggable ? 'grab' : 'default')\n canvas.hoverCursor = draggable ? 'grab' : 'default'\n canvas.requestRenderAll()\n }\n },\n setZoomable: zoomable => {\n set({ zoomable })\n },\n\n setIsDragging: isDragging => {\n set({ isDragging })\n },\n setSelection: selection => {\n const canvas = get().canvas\n if (!canvas) return\n set({ selection })\n canvas.set('selection', selection)\n canvas.requestRenderAll()\n },\n setDefaultDraggable: defaultDraggable => {\n if (defaultDraggable === undefined) return\n const { setDraggable } = get()\n set({ hasDefaultDraggable: true })\n setDraggable(defaultDraggable)\n },\n setDefaultSelection: defaultSelection => {\n if (defaultSelection === undefined) return\n const { setSelection } = get()\n set({ hasDefaultSelection: true })\n setSelection(defaultSelection)\n },\n setFitZoom: (fitZoom: number) => {\n set({ fitZoom: fitZoom })\n },\n setManualZoom: (manualZoom: number) => {\n set({ manualZoom: manualZoom })\n },\n setMinManualZoom: (zoom: number) => {\n set({ minManualZoom: zoom })\n },\n setZoom: (zoom: number) => {\n set({ zoom: zoom })\n },\n setMaxManualZoom: (zoom: number) => {\n set({ maxManualZoom: zoom })\n },\n\n reset: () => set({ ...getInitialState() }),\n }),\n Object.is,\n )\n\nexport { createStore }\n"],"names":["createStore","nodes","defaultNodes","width","height","createWithEqualityFn","set","get","getInitialState","options","currentState","newDimensions","loading","draggable","canvas","zoomable","isDragging","selection","defaultDraggable","setDraggable","defaultSelection","setSelection","fitZoom","manualZoom","zoom"],"mappings":"kFAKMA,MAAAA,EAAc,CAAC,CACnB,MAAAC,EACA,aAAAC,EACA,MAAAC,EACA,OAAAC,CACF,IAMEC,EAAAA,qBACE,CAACC,EAAKC,KAAS,CACb,GAAGC,UAAgB,CAAE,MAAAP,EAAO,MAAAE,EAAO,OAAAC,EAAQ,aAAAF,CAAa,CAAC,EACzD,cAAgBO,GAAiD,CAC/D,KAAM,CAAE,MAAAN,EAAO,OAAAC,CAAO,EAAIK,EACpBC,EAAeH,EAAI,EAGnBI,EAAgB,CACpB,MAAOR,GAASO,EAAa,MAC7B,OAAQN,GAAUM,EAAa,MACjC,EAEAH,IAAM,QAAQ,cAAcI,CAAa,EACzCL,EAAIK,CAAa,CACnB,EACA,WAAYC,GAAW,CACrBN,EAAI,CAAE,QAAAM,CAAQ,CAAC,CACjB,EACA,aAAcC,GAAa,CACzBP,EAAI,CAAE,UAAAO,CAAU,CAAC,EACjB,MAAMC,EAASP,EAAI,EAAE,OAEjBO,IACFA,EAAO,UAAUD,EAAY,OAAS,SAAS,EAC/CC,EAAO,YAAcD,EAAY,OAAS,UAC1CC,EAAO,mBAEX,EACA,YAAaC,GAAY,CACvBT,EAAI,CAAE,SAAAS,CAAS,CAAC,CAClB,EAEA,cAAeC,GAAc,CAC3BV,EAAI,CAAE,WAAAU,CAAW,CAAC,CACpB,EACA,aAAcC,GAAa,CACzB,MAAMH,EAASP,EAAM,EAAA,OAChBO,IACLR,EAAI,CAAE,UAAAW,CAAU,CAAC,EACjBH,EAAO,IAAI,YAAaG,CAAS,EACjCH,EAAO,iBAAiB,EAC1B,EACA,oBAAqBI,GAAoB,CACvC,GAAIA,IAAqB,OAAW,OACpC,KAAM,CAAE,aAAAC,CAAa,EAAIZ,EAAI,EAC7BD,EAAI,CAAE,oBAAqB,EAAK,CAAC,EACjCa,EAAaD,CAAgB,CAC/B,EACA,oBAAqBE,GAAoB,CACvC,GAAIA,IAAqB,OAAW,OACpC,KAAM,CAAE,aAAAC,CAAa,EAAId,EACzBD,EAAAA,EAAI,CAAE,oBAAqB,EAAK,CAAC,EACjCe,EAAaD,CAAgB,CAC/B,EACA,WAAaE,GAAoB,CAC/BhB,EAAI,CAAE,QAASgB,CAAQ,CAAC,CAC1B,EACA,cAAgBC,GAAuB,CACrCjB,EAAI,CAAE,WAAYiB,CAAW,CAAC,CAChC,EACA,iBAAmBC,GAAiB,CAClClB,EAAI,CAAE,cAAekB,CAAK,CAAC,CAC7B,EACA,QAAUA,GAAiB,CACzBlB,EAAI,CAAE,KAAMkB,CAAK,CAAC,CACpB,EACA,iBAAmBA,GAAiB,CAClClB,EAAI,CAAE,cAAekB,CAAK,CAAC,CAC7B,EAEA,MAAO,IAAMlB,EAAI,CAAE,GAAGE,EAAgB,QAAA,CAAE,CAAC,CAC3C,GACA,OAAO,EACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const d=({nodes:o,defaultNodes:e,defaultSelection:a,defaultDraggable:l}={})=>({width:200,height:200,canvas:null,nodes:e??o??[],onNodesChange:null,hasDefaultNodes:e!==void 0,hasDefaultSelection:a!==void 0,hasDefaultDraggable:l!==void 0,zoom:1,minManualZoom:.4,maxManualZoom:3,domNode:null,debug:!1,isDragging:!1,selection:a??!0,zoomable:!0,draggable:!1,scale:1,lastPosX:void 0,lastPosY:void 0,loading:!1,fitZoom:1,manualZoom:1,defaultCentered:!1});exports.default=d;
|
|
2
|
+
//# sourceMappingURL=initialState.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initialState.cjs","sources":["../../../src/store/initialState.ts"],"sourcesContent":["import type { Node } from '../types/nodes'\nimport type { ReactFabricStore } from '../types/store'\n\nconst getInitialState = ({\n nodes,\n defaultNodes,\n defaultSelection,\n defaultDraggable,\n}: {\n nodes?: Node[]\n defaultNodes?: Node[]\n width?: number\n defaultSelection?: boolean\n defaultDraggable?: boolean\n height?: number\n} = {}): ReactFabricStore => {\n const storeNodes = defaultNodes ?? nodes ?? []\n\n return {\n width: 200,\n height: 200,\n canvas: null,\n nodes: storeNodes,\n onNodesChange: null,\n hasDefaultNodes: defaultNodes !== undefined,\n hasDefaultSelection: defaultSelection !== undefined,\n hasDefaultDraggable: defaultDraggable !== undefined,\n zoom: 1,\n minManualZoom: 0.4,\n maxManualZoom: 3,\n domNode: null,\n debug: false,\n isDragging: false,\n selection: defaultSelection ?? true, // 必须跟着 fabric 默认值 true\n zoomable: true,\n draggable: false,\n scale: 1,\n lastPosX: undefined,\n lastPosY: undefined,\n loading: false,\n fitZoom: 1,\n manualZoom: 1,\n defaultCentered: false,\n }\n}\n\nexport default getInitialState\n"],"names":["getInitialState","nodes","defaultNodes","defaultSelection","defaultDraggable"],"mappings":"oEAGA,MAAMA,EAAkB,CAAC,CACvB,MAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,iBAAAC,CACF,EAOI,CAAA,KAGK,CACL,MAAO,IACP,OAAQ,IACR,OAAQ,KACR,MANiBF,GAAgBD,GAAS,CAAA,EAO1C,cAAe,KACf,gBAAiBC,IAAiB,OAClC,oBAAqBC,IAAqB,OAC1C,oBAAqBC,IAAqB,OAC1C,KAAM,EACN,cAAe,GACf,cAAe,EACf,QAAS,KACT,MAAO,GACP,WAAY,GACZ,UAAWD,GAAoB,GAC/B,SAAU,GACV,UAAW,GACX,MAAO,EACP,SAAU,OACV,SAAU,OACV,QAAS,GACT,QAAS,EACT,WAAY,EACZ,gBAAiB,EACnB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),x=require("tailwind-merge"),m=require("../../hooks/useReactFabric.cjs");const p=({className:t})=>{const{manualZoom:r,zoomIn:a,zoomOut:c,maxManualZoom:n,minManualZoom:o,draggable:s,setDraggable:i,resetViewport:l}=m.useReactFabric();return e.jsxs("section",{className:x.twMerge("flex flex-col items-center p-[10px_7px] bg-[#f7f7f7] rounded-lg gap-4",t),children:[e.jsxs("div",{className:"flex flex-col items-center",children:[e.jsx("div",{className:"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]",children:e.jsx("span",{className:`iconfont T_narrow text-[25px] ${Number(r.toFixed(2))<=o?"text-[#c4c4c4]":""}`,onClick:c})}),e.jsxs("span",{className:"inline-block text-center my-[6px] text-sm font-semibold leading-[22px] min-w-[40px]",children:[" ",Math.round(r*100),"%"]}),e.jsx("div",{className:"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]",children:e.jsx("span",{className:`iconfont T_enlarge text-[25px] ${Number(r.toFixed(2))>=n?"text-[#c4c4c4]":""}`,onClick:a})})]}),e.jsx("div",{onClick:()=>i(!s),className:`w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)] ${s?"bg-[#04aa65]":""}`,children:e.jsx("span",{className:"iconfont T_drag text-[25px]"})}),e.jsx("div",{className:"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]",onClick:l,children:e.jsx("span",{className:"iconfont T_reset text-[25px]"})})]})};exports.default=p;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/toolbar/Vertical/index.tsx"],"sourcesContent":["import { twMerge } from 'tailwind-merge'\nimport { useReactFabric } from '../../hooks/useReactFabric'\n\nexport type ToolbarVerticalProps = {\n className?: string\n}\n\n/**\n *@desc 垂直toolbar\n * @returns\n */\nconst ToolbarVertical = ({ className }: ToolbarVerticalProps) => {\n const { manualZoom, zoomIn, zoomOut, maxManualZoom, minManualZoom, draggable, setDraggable, resetViewport } =\n useReactFabric()\n\n return (\n <section\n className={twMerge('flex flex-col items-center p-[10px_7px] bg-[#f7f7f7] rounded-lg gap-4', className)}\n >\n {/* fabric-tool */}\n <div className=\"flex flex-col items-center\">\n {/* scale-view */}\n <div className=\"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]\">\n {/* ic-tool-box */}\n <span\n className={`iconfont T_narrow text-[25px] ${Number(manualZoom.toFixed(2)) <= minManualZoom ? 'text-[#c4c4c4]' : ''}`}\n onClick={zoomOut}\n ></span>\n </div>\n <span className=\"inline-block text-center my-[6px] text-sm font-semibold leading-[22px] min-w-[40px]\">\n {' '}\n {/* scale-num */}\n {Math.round(manualZoom * 100)}%\n </span>\n <div className=\"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]\">\n <span\n className={`iconfont T_enlarge text-[25px] ${Number(manualZoom.toFixed(2)) >= maxManualZoom ? 'text-[#c4c4c4]' : ''}`}\n onClick={zoomIn}\n ></span>\n </div>\n </div>\n <div\n onClick={() => setDraggable(!draggable)}\n className={`w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)] ${\n draggable ? 'bg-[#04aa65]' : ''\n }`}\n >\n <span className=\"iconfont T_drag text-[25px]\"></span>\n </div>\n <div\n className=\"w-[30px] h-[30px] flex items-center justify-center rounded cursor-pointer hover:bg-[var(--color-primary)]\"\n onClick={resetViewport}\n >\n <span className=\"iconfont T_reset text-[25px]\"></span>\n </div>\n </section>\n )\n}\n\nexport default ToolbarVertical\n"],"names":["ToolbarVertical","className","manualZoom","zoomIn","zoomOut","maxManualZoom","minManualZoom","draggable","setDraggable","resetViewport","useReactFabric","jsxs","twMerge","jsx"],"mappings":"+KAWMA,MAAAA,EAAkB,CAAC,CAAE,UAAAC,CAAU,IAA4B,CAC/D,KAAM,CAAE,WAAAC,EAAY,OAAAC,EAAQ,QAAAC,EAAS,cAAAC,EAAe,cAAAC,EAAe,UAAAC,EAAW,aAAAC,EAAc,cAAAC,CAAc,EACxGC,EAAAA,iBAEF,OACEC,OAAC,UACC,CAAA,UAAWC,EAAQ,QAAA,wEAAyEX,CAAS,EAGrG,SAAA,CAAAU,EAAAA,KAAC,MAAA,CAAI,UAAU,6BAEX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,4GAEb,SAAAA,EAAAA,IAAC,OAAA,CACC,UAAW,iCAAiC,OAAOX,EAAW,QAAQ,CAAC,CAAC,GAAKI,EAAgB,iBAAmB,EAAE,GAClH,QAASF,CACV,CAAA,CAAA,CACH,EACFO,OAAC,OAAK,CAAA,UAAU,sFACb,SAEA,CAAA,IAAA,KAAK,MAAMT,EAAa,GAAG,EAAE,GAAA,CAAA,CAChC,EACEW,EAAAA,IAAC,OAAI,UAAU,4GACb,SAAAA,EAAAA,IAAC,OACC,CAAA,UAAW,kCAAkC,OAAOX,EAAW,QAAQ,CAAC,CAAC,GAAKG,EAAgB,iBAAmB,EAAE,GACnH,QAASF,EACV,CACH,CAAA,CAAA,CAAA,CACJ,EACEU,MAAC,MACC,CAAA,QAAS,IAAML,EAAa,CAACD,CAAS,EACtC,UAAW,6GACTA,EAAY,eAAiB,EAC/B,GAEA,SAAAM,MAAC,OAAK,CAAA,UAAU,6BAA8B,CAAA,CAAA,CAChD,EACAA,EAAC,IAAA,MAAA,CACC,UAAU,4GACV,QAASJ,EAET,SAAAI,EAAC,IAAA,OAAA,CAAK,UAAU,8BAA+B,CAAA,CAAA,CACjD,CACJ,CAAA,CAAA,CAEJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-props.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.cjs","sources":["../../../src/utils/constants.ts"],"sourcesContent":["// 定义位置相关属性的类型\nexport type UncontrolledProp =\n | 'left'\n | 'top'\n | 'width'\n | 'height'\n | 'scaleX'\n | 'scaleY'\n | 'angle'\n | 'points'\n | 'path'\n | 'originX'\n | 'originY'\n\n// 定义可以非受控的属性\nexport const UNCONTROLLED_PROPS = [\n 'left',\n 'top',\n 'width',\n 'height',\n 'scaleX',\n 'scaleY',\n 'angle',\n 'points',\n 'path',\n 'originX',\n 'originY',\n] as readonly UncontrolledProp[]\n\n// 定义默认属性的类型\nexport type DefaultProp = `default${Capitalize<UncontrolledProp>}`\n\n// 生成对应的 default 属性\nexport const DEFAULT_PROPS = UNCONTROLLED_PROPS.map(\n prop => `default${prop.charAt(0).toUpperCase()}${prop.slice(1)}` as DefaultProp,\n) as readonly DefaultProp[]\n"],"names":["UNCONTROLLED_PROPS","DEFAULT_PROPS","prop"],"mappings":"aAeO,MAAMA,EAAqB,CAChC,OACA,MACA,QACA,SACA,SACA,SACA,QACA,SACA,OACA,UACA,SACF,EAMaC,EAAgBD,EAAmB,IAC9CE,GAAQ,UAAUA,EAAK,OAAO,CAAC,EAAE,YAAa,CAAA,GAAGA,EAAK,MAAM,CAAC,CAAC,EAChE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.cjs","sources":["../../../src/utils/dom.ts"],"sourcesContent":["import type { Dimensions } from '../types/utils'\n\nexport const getDimensions = (node: HTMLCanvasElement): Dimensions => ({\n width: node.offsetWidth,\n height: node.offsetHeight,\n})\n"],"names":["getDimensions","node"],"mappings":"aAEa,MAAAA,EAAiBC,IAAyC,CACrE,MAAOA,EAAK,YACZ,OAAQA,EAAK,YACf"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const f=(n,r)=>{const s=[];return Object.entries(r).forEach(([e,o])=>{if(o){const t=e.slice(2).replace(/[A-Z]/g,(c,i)=>i===0?c.toLowerCase():":"+c.toLowerCase());n.on(t,o),s.push(()=>n.off(t,o))}}),()=>s.forEach(e=>e())};exports.bindEvents=f;
|
|
2
|
+
//# sourceMappingURL=events.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.cjs","sources":["../../../src/utils/events.ts"],"sourcesContent":["import type { CanvasEvents, GroupEvents, ObjectEvents } from 'fabric'\nimport type { AllCanvasEvents } from '../types/canvas'\nimport type { AllObjectEvents } from '../types/object'\n\nexport const bindEvents = <T extends CanvasEvents | ObjectEvents | GroupEvents>(\n target: any,\n listeners: Partial<T extends CanvasEvents ? AllCanvasEvents : AllObjectEvents>,\n) => {\n const cleanup: (() => void)[] = []\n\n Object.entries(listeners).forEach(([key, handler]) => {\n if (handler) {\n const rawEventName = key\n .slice(2)\n .replace(/[A-Z]/g, (match, offset) =>\n offset === 0 ? match.toLowerCase() : ':' + match.toLowerCase(),\n ) as keyof T\n\n target.on(rawEventName, handler)\n cleanup.push(() => target.off(rawEventName, handler))\n }\n })\n\n return () => cleanup.forEach(fn => fn())\n}\n"],"names":["bindEvents","target","listeners","cleanup","key","handler","rawEventName","match","offset","fn"],"mappings":"aAIO,MAAMA,EAAa,CACxBC,EACAC,IACG,CACH,MAAMC,EAA0B,GAEhC,OAAA,OAAO,QAAQD,CAAS,EAAE,QAAQ,CAAC,CAACE,EAAKC,CAAO,IAAM,CACpD,GAAIA,EAAS,CACX,MAAMC,EAAeF,EAClB,MAAM,CAAC,EACP,QAAQ,SAAU,CAACG,EAAOC,IACzBA,IAAW,EAAID,EAAM,YAAY,EAAI,IAAMA,EAAM,YACnD,CAAA,EAEFN,EAAO,GAAGK,EAAcD,CAAO,EAC/BF,EAAQ,KAAK,IAAMF,EAAO,IAAIK,EAAcD,CAAO,CAAC,CACtD,CACF,CAAC,EAEM,IAAMF,EAAQ,QAAQM,GAAMA,EAAAA,CAAI,CACzC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const h=(e,r)=>{if(!e||!r)return!1;const t=Array.isArray(e)?e:e.split(",").map(Number),u=Array.isArray(r)?r:r.split(",").map(Number);if(t.length!==8||u.length!==8)return!1;const[a,n,m,i,l,p,s,b]=t.map(Number),[c,y,f,o,A,N,d,g]=u.map(Number);return c>=a&&y>=n&&f<=m&&o>=i&&A<=l&&N<=p&&d>=s&&g<=b};exports.default=h;
|
|
2
|
+
//# sourceMappingURL=position.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"position.cjs","sources":["../../../src/utils/position.ts"],"sourcesContent":["/**\n * 判断sunPosition是否在parentPosition内\n * @param parentPosition 父级位置 (格式: x1,y1,x2,y2,x3,y3,x4,y4)\n * @param sunPosition 子级位置 (格式: x1,y1,x2,y2,x3,y3,x4,y4)\n * @returns boolean\n */\nconst includes = (parentPosition: string | number[], sunPosition: string | number[]) => {\n if (!parentPosition || !sunPosition) return false\n\n // 转换为数组\n const parentPoints = Array.isArray(parentPosition) ? parentPosition : parentPosition.split(',').map(Number)\n const sunPoints = Array.isArray(sunPosition) ? sunPosition : sunPosition.split(',').map(Number)\n\n // 验证坐标点数量\n if (parentPoints.length !== 8 || sunPoints.length !== 8) return false\n\n // 转换为数字并解构\n const [x1, y1, x2, y2, x3, y3, x4, y4] = parentPoints.map(Number)\n const [x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s] = sunPoints.map(Number)\n\n return x1s >= x1 && y1s >= y1 && x2s <= x2 && y2s >= y2 && x3s <= x3 && y3s <= y3 && x4s >= x4 && y4s <= y4\n}\n\nexport default includes\n"],"names":["includes","parentPosition","sunPosition","parentPoints","sunPoints","x1","y1","x2","y2","x3","y3","x4","y4","x1s","y1s","x2s","y2s","x3s","y3s","x4s","y4s"],"mappings":"oEAMMA,MAAAA,EAAW,CAACC,EAAmCC,IAAmC,CACtF,GAAI,CAACD,GAAkB,CAACC,EAAa,MAAO,GAG5C,MAAMC,EAAe,MAAM,QAAQF,CAAc,EAAIA,EAAiBA,EAAe,MAAM,GAAG,EAAE,IAAI,MAAM,EACpGG,EAAY,MAAM,QAAQF,CAAW,EAAIA,EAAcA,EAAY,MAAM,GAAG,EAAE,IAAI,MAAM,EAG9F,GAAIC,EAAa,SAAW,GAAKC,EAAU,SAAW,EAAG,MAAO,GAGhE,KAAM,CAACC,EAAIC,EAAIC,EAAIC,EAAIC,EAAIC,EAAIC,EAAIC,CAAE,EAAIT,EAAa,IAAI,MAAM,EAC1D,CAACU,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,EAAKC,CAAG,EAAIhB,EAAU,IAAI,MAAM,EAErE,OAAOS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,GAAMS,GAAOR,CAC3G"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const i=o=>Object.entries(o).reduce(([t,e],[r,s])=>(r.startsWith("on")?t[r]=s:e[r]=s,[t,e]),[{},{}]),c=o=>Object.entries(o).reduce((t,[e,r])=>{if(e.startsWith("default")){const s=e.replace(/^default([A-Z])/,(n,a)=>a.toLowerCase());t[s]=r}return t},{});exports.splitListenerProps=i,exports.transformDefaultProps=c;
|
|
2
|
+
//# sourceMappingURL=props.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props.cjs","sources":["../../../src/utils/props.ts"],"sourcesContent":["import type { AllCanvasEvents } from '../types/canvas'\n\nexport const splitListenerProps = <T extends Record<string, any>>(\n props: T,\n): [{ [K in keyof AllCanvasEvents]?: AllCanvasEvents[K] }, Omit<T, keyof AllCanvasEvents>] => {\n return Object.entries(props).reduce(\n ([listeners, options], [key, value]) => {\n if (key.startsWith('on')) {\n ;(listeners as any)[key] = value\n } else {\n ;(options as any)[key] = value\n }\n return [listeners, options]\n },\n [{} as { [K in keyof AllCanvasEvents]?: AllCanvasEvents[K] }, {} as Omit<T, keyof AllCanvasEvents>],\n )\n}\n\n// 工具函数:转换 default 属性\nexport const transformDefaultProps = (defaultValues: Record<string, unknown>) => {\n return Object.entries(defaultValues).reduce(\n (acc, [key, value]) => {\n if (key.startsWith('default')) {\n // 使用正则替换 'default' 并将首字母小写\n const propName = key.replace(/^default([A-Z])/, (_, c) => c.toLowerCase())\n acc[propName] = value\n }\n return acc\n },\n {} as Record<string, unknown>,\n )\n}\n"],"names":["splitListenerProps","props","listeners","options","key","value","transformDefaultProps","defaultValues","acc","propName","_","c"],"mappings":"aAEO,MAAMA,EACXC,GAEO,OAAO,QAAQA,CAAK,EAAE,OAC3B,CAAC,CAACC,EAAWC,CAAO,EAAG,CAACC,EAAKC,CAAK,KAC5BD,EAAI,WAAW,IAAI,EACnBF,EAAkBE,CAAG,EAAIC,EAEzBF,EAAgBC,CAAG,EAAIC,EAEpB,CAACH,EAAWC,CAAO,GAE5B,CAAC,CAAA,EAA6D,CAAA,CAAoC,CACpG,EAIWG,EAAyBC,GAC7B,OAAO,QAAQA,CAAa,EAAE,OACnC,CAACC,EAAK,CAACJ,EAAKC,CAAK,IAAM,CACrB,GAAID,EAAI,WAAW,SAAS,EAAG,CAE7B,MAAMK,EAAWL,EAAI,QAAQ,kBAAmB,CAACM,EAAGC,IAAMA,EAAE,YAAa,CAAA,EACzEH,EAAIC,CAAQ,EAAIJ,CAClB,CACA,OAAOG,CACT,EACA,CACF,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{util as h,FabricImage as C}from"fabric";import{forwardRef as F,useRef as R,useCallback as A,useEffect as v,useImperativeHandle as V,memo as x}from"react";import{useDidUpdate as j}from"../../hooks/useDidUpdate.mjs";import{useStoreApi as q,useStore as y}from"../../hooks/useStore.mjs";const E=n=>({width:n.width,height:n.height}),L=F(({src:n,onLoad:w,onScaling:Z,scaleToFit:u,scaleToCover:l,...g},p)=>{const r=R(null),a=q(),{width:b,height:S}=y(E),m=A(c=>{const{canvas:e,manualZoom:t=1,defaultCentered:o}=a.getState();if(!r.current)return;if(!e){console.warn("updateViewport: !canvas");return}if(!e.backgroundImage){console.warn("updateViewport: !canvas.backgroundImage");return}const i=c.scaleToFit?h.findScaleToFit(r.current,e):c.scaleToCover?h.findScaleToCover(r.current,e):1,s=i*t;e.setViewportTransform([s,0,0,s,0,0]);let d=0,f=0;if(o&&e.backgroundImage){const I=e.backgroundImage.width||0,k=e.backgroundImage.height||0;d=(e.width-I*s)/2,f=(e.height-k*s)/2}const T=[s,0,0,s,d,f];e.setViewportTransform(T),e.requestRenderAll(),a.setState({fitZoom:i,manualZoom:t,zoom:s})},[a]);return v(()=>{m({scaleToFit:u,scaleToCover:l})},[b,S,u,l,m,a]),v(()=>{if(!n){console.warn("ReactFabricBackgroundImage: !src");return}const{domNode:c,setLoading:e}=a.getState();return e(!0),C.fromURL(n,{crossOrigin:"anonymous"}).then(t=>{const{canvas:o}=a.getState();if(o){const i={...g,angle:0};if(t.set({...i,objectCaching:!1}),o.getContext().imageSmoothingEnabled=!0,o.getContext().imageSmoothingQuality="high",o.backgroundImage=t,r.current=t,requestAnimationFrame(()=>{m({scaleToFit:u,scaleToCover:l})}),!o.viewportTransform){console.warn("!viewport");return}w?.(t)}else console.warn("ReactFabric:BackgroundImage: !canvas",o)}).catch(console.error).finally(()=>{c&&(c.dataset.src=n),e(!1)}),()=>{const{canvas:t}=a.getState();t?.backgroundImage&&(t.backgroundImage=void 0,t.remove(r.current),r.current=null,t.renderAll())}},[n]),j(()=>{const{canvas:c}=a.getState();r.current&&(Object.entries(g).forEach(([e,t])=>{e==="angle"?r.current?.rotate(t):r.current?.set(e,t)}),c?.requestRenderAll())},[g,a]),V(p,()=>({instance:r.current})),null});var O=x(L);export{O as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/BackgroundImage/index.tsx"],"sourcesContent":["import type {\n BasicTransformEvent,\n ImageProps,\n ObjectEvents,\n SerializedImageProps,\n TDegree,\n TPointerEvent,\n} from 'fabric'\nimport { FabricImage, util } from 'fabric'\nimport { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nexport type Handle = {}\n\ntype ScaleMode = {\n scaleToFit?: boolean\n scaleToCover?: boolean\n}\nexport type BackgroundImageProps = Partial<ImageProps> & {\n src: string\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void\n\n /** 自动缩放至容器宽高 */\n} & ScaleMode\n\nconst selector = (s: ReactFabricState) => ({\n width: s.width,\n height: s.height,\n})\n\nconst BackgroundImage = forwardRef<Handle, BackgroundImageProps>(\n ({ src, onLoad, onScaling, scaleToFit, scaleToCover, ...options }, ref) => {\n const backgroundImageRef = useRef<FabricImage | null>(null)\n\n const store = useStoreApi()\n\n const { width, height } = useStore(selector)\n\n const updateViewport = useCallback(\n (params: { scaleToFit?: boolean; scaleToCover?: boolean }) => {\n const { canvas, manualZoom = 1, defaultCentered } = store.getState()\n if (!backgroundImageRef.current) {\n return\n }\n if (!canvas) {\n console.warn('updateViewport: !canvas')\n return\n }\n if (!canvas.backgroundImage) {\n console.warn('updateViewport: !canvas.backgroundImage')\n return\n }\n\n // 1. 计算缩放\n const fitZoom = params.scaleToFit\n ? util.findScaleToFit(backgroundImageRef.current, canvas)\n : params.scaleToCover\n ? util.findScaleToCover(backgroundImageRef.current, canvas)\n : 1\n\n const combinedZoom = fitZoom * manualZoom\n\n // 2. 先应用基础缩放\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n\n // 3. 如果需要居中,计算偏移量\n let deltaX = 0\n let deltaY = 0\n\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n // const canvasCenter = {\n // x: canvas.width! / 2,\n // y: canvas.height! / 2,\n // }\n // const bgCenter = {\n // x:\n // (canvas.backgroundImage.left! + (canvas.backgroundImage.width! * canvas.backgroundImage.scaleX!) / 2) *\n // combinedZoom,\n // y:\n // (canvas.backgroundImage.top! + (canvas.backgroundImage.height! * canvas.backgroundImage.scaleY!) / 2) *\n // combinedZoom,\n // }\n // deltaX = canvasCenter.x - bgCenter.x\n // deltaY = canvasCenter.y - bgCenter.y\n }\n\n // 4. 应用最终变换\n const finalTransform: [number, number, number, number, number, number] = [\n combinedZoom,\n 0,\n 0,\n combinedZoom,\n deltaX,\n deltaY,\n ]\n\n canvas.setViewportTransform(finalTransform)\n canvas.requestRenderAll()\n\n // 5. 更新 store\n store.setState({\n fitZoom,\n manualZoom,\n zoom: combinedZoom,\n })\n },\n [store],\n )\n\n // 监听 width, height 的变化\n useEffect(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n }, [width, height, scaleToFit, scaleToCover, updateViewport, store])\n\n useEffect(() => {\n if (!src) {\n console.warn('ReactFabricBackgroundImage: !src')\n return\n }\n const { domNode, setLoading } = store.getState()\n setLoading(true)\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n .then(imageSource => {\n const { canvas } = store.getState()\n if (canvas) {\n // 初始化时角度的旋转,一定要放到 updateViewport 之后;先画正图片,再进行旋转\n const removeAngleOptions = { ...options, angle: 0 }\n imageSource.set({\n ...removeAngleOptions,\n objectCaching: false,\n })\n canvas.getContext().imageSmoothingEnabled = true\n canvas.getContext().imageSmoothingQuality = 'high'\n canvas.backgroundImage = imageSource\n backgroundImageRef.current = imageSource\n\n requestAnimationFrame(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n })\n\n const viewport = canvas.viewportTransform\n if (!viewport) {\n console.warn('!viewport')\n return\n }\n\n // imageSource.angle = options.angle || 0\n onLoad?.(imageSource)\n } else {\n console.warn('ReactFabric:BackgroundImage: !canvas', canvas)\n }\n })\n .catch(console.error)\n .finally(() => {\n if (domNode) domNode.dataset.src = src\n setLoading(false)\n })\n\n return () => {\n const { canvas } = store.getState()\n if (canvas?.backgroundImage) {\n canvas.backgroundImage = undefined\n canvas.remove(backgroundImageRef.current!)\n backgroundImageRef.current = null\n canvas.renderAll()\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [src])\n\n useDidUpdate(() => {\n const { canvas } = store.getState()\n\n if (backgroundImageRef.current) {\n Object.entries(options).forEach(([key, value]) => {\n if (key === 'angle') {\n backgroundImageRef.current?.rotate(value as TDegree)\n } else {\n backgroundImageRef.current?.set(key, value)\n }\n })\n canvas?.requestRenderAll()\n }\n }, [options, store])\n\n useImperativeHandle(ref, () => ({\n // 是最新的?\n instance: backgroundImageRef.current,\n }))\n\n return null\n },\n)\n\nexport default memo(BackgroundImage)\n"],"names":["selector","s","BackgroundImage","forwardRef","src","onLoad","onScaling","scaleToFit","scaleToCover","options","ref","backgroundImageRef","useRef","store","useStoreApi","width","height","useStore","updateViewport","useCallback","params","canvas","manualZoom","defaultCentered","fitZoom","util","combinedZoom","deltaX","deltaY","bgWidth","bgHeight","finalTransform","useEffect","domNode","setLoading","FabricImage","imageSource","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"+SA4BA,MAAMA,EAAYC,IAAyB,CACzC,MAAOA,EAAE,MACT,OAAQA,EAAE,MACZ,GAEMC,EAAkBC,EACtB,CAAC,CAAE,IAAAC,EAAK,OAAAC,EAAQ,UAAAC,EAAW,WAAAC,EAAY,aAAAC,EAAc,GAAGC,CAAQ,EAAGC,IAAQ,CACzE,MAAMC,EAAqBC,EAA2B,IAAI,EAEpDC,EAAQC,IAER,CAAE,MAAAC,EAAO,OAAAC,CAAO,EAAIC,EAASjB,CAAQ,EAErCkB,EAAiBC,EACpBC,GAA6D,CAC5D,KAAM,CAAE,OAAAC,EAAQ,WAAAC,EAAa,EAAG,gBAAAC,CAAgB,EAAIV,EAAM,SAAS,EACnE,GAAI,CAACF,EAAmB,QACtB,OAEF,GAAI,CAACU,EAAQ,CACX,QAAQ,KAAK,yBAAyB,EACtC,MACF,CACA,GAAI,CAACA,EAAO,gBAAiB,CAC3B,QAAQ,KAAK,yCAAyC,EACtD,MACF,CAGA,MAAMG,EAAUJ,EAAO,WACnBK,EAAK,eAAed,EAAmB,QAASU,CAAM,EACtDD,EAAO,aACLK,EAAK,iBAAiBd,EAAmB,QAASU,CAAM,EACxD,EAEAK,EAAeF,EAAUF,EAG/BD,EAAO,qBAAqB,CAACK,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAGpE,IAAIC,EAAS,EACTC,EAAS,EAEb,GAAIL,GAAmBF,EAAO,gBAAiB,CAC7C,MAAMQ,EAAUR,EAAO,gBAAgB,OAAS,EAC1CS,EAAWT,EAAO,gBAAgB,QAAU,EAClDM,GAAUN,EAAO,MAASQ,EAAUH,GAAgB,EACpDE,GAAUP,EAAO,OAAUS,EAAWJ,GAAgB,CAexD,CAGA,MAAMK,EAAmE,CACvEL,EACA,EACA,EACAA,EACAC,EACAC,CACF,EAEAP,EAAO,qBAAqBU,CAAc,EAC1CV,EAAO,iBAGPR,EAAAA,EAAM,SAAS,CACb,QAAAW,EACA,WAAAF,EACA,KAAMI,CACR,CAAC,CACH,EACA,CAACb,CAAK,CACR,EAGA,OAAAmB,EAAU,IAAM,CACdd,EAAe,CACb,WAAAX,EACA,aAAAC,CACF,CAAC,CACH,EAAG,CAACO,EAAOC,EAAQT,EAAYC,EAAcU,EAAgBL,CAAK,CAAC,EAEnEmB,EAAU,IAAM,CACd,GAAI,CAAC5B,EAAK,CACR,QAAQ,KAAK,kCAAkC,EAC/C,MACF,CACA,KAAM,CAAE,QAAA6B,EAAS,WAAAC,CAAW,EAAIrB,EAAM,WACtC,OAAAqB,EAAW,EAAI,EACfC,EAAY,QAAQ/B,EAAK,CAAE,YAAa,WAAY,CAAC,EAClD,KAAKgC,GAAe,CACnB,KAAM,CAAE,OAAAf,CAAO,EAAIR,EAAM,SAAS,EAClC,GAAIQ,EAAQ,CAEV,MAAMgB,EAAqB,CAAE,GAAG5B,EAAS,MAAO,CAAE,EAkBlD,GAjBA2B,EAAY,IAAI,CACd,GAAGC,EACH,cAAe,EACjB,CAAC,EACDhB,EAAO,WAAA,EAAa,sBAAwB,GAC5CA,EAAO,WAAW,EAAE,sBAAwB,OAC5CA,EAAO,gBAAkBe,EACzBzB,EAAmB,QAAUyB,EAE7B,sBAAsB,IAAM,CAC1BlB,EAAe,CACb,WAAAX,EACA,aAAAC,CACF,CAAC,CACH,CAAC,EAGG,CADaa,EAAO,kBACT,CACb,QAAQ,KAAK,WAAW,EACxB,MACF,CAGAhB,IAAS+B,CAAW,CACtB,MACE,QAAQ,KAAK,uCAAwCf,CAAM,CAE/D,CAAC,EACA,MAAM,QAAQ,KAAK,EACnB,QAAQ,IAAM,CACTY,IAASA,EAAQ,QAAQ,IAAM7B,GACnC8B,EAAW,EAAK,CAClB,CAAC,EAEI,IAAM,CACX,KAAM,CAAE,OAAAb,CAAO,EAAIR,EAAM,SACrBQ,EAAAA,GAAQ,kBACVA,EAAO,gBAAkB,OACzBA,EAAO,OAAOV,EAAmB,OAAQ,EACzCA,EAAmB,QAAU,KAC7BU,EAAO,UAAU,EAErB,CAEF,EAAG,CAACjB,CAAG,CAAC,EAERkC,EAAa,IAAM,CACjB,KAAM,CAAE,OAAAjB,CAAO,EAAIR,EAAM,SAAS,EAE9BF,EAAmB,UACrB,OAAO,QAAQF,CAAO,EAAE,QAAQ,CAAC,CAAC8B,EAAKC,CAAK,IAAM,CAC5CD,IAAQ,QACV5B,EAAmB,SAAS,OAAO6B,CAAgB,EAEnD7B,EAAmB,SAAS,IAAI4B,EAAKC,CAAK,CAE9C,CAAC,EACDnB,GAAQ,iBAAA,EAEZ,EAAG,CAACZ,EAASI,CAAK,CAAC,EAEnB4B,EAAoB/B,EAAK,KAAO,CAE9B,SAAUC,EAAmB,OAC/B,EAAE,EAEK,IACT,CACF,EAEA,MAAe+B,EAAKxC,CAAe"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsxs as x,jsx as z}from"react/jsx-runtime";import{Canvas as E,Point as w}from"fabric";import{useRef as c,useLayoutEffect as Z,useEffect as u}from"react";import g from"../../hooks/useDraggable.mjs";import y from"../../hooks/useResizeHandler.mjs";import{useSplitProps as A}from"../../hooks/useSplitProps.mjs";import{useStoreApi as D}from"../../hooks/useStore.mjs";import{bindEvents as M}from"../../utils/events.mjs";const j={position:"absolute",width:"100%",height:"100%",top:0,left:0},N=({children:h,onMouseWheel:l,...S})=>{const e=c(),o=D(),i=c(null);g();const m=c(null),[b,s]=A(S);return Z(()=>{const n=i.current;e.current=new E(n||void 0,{...s});const t=M(e.current,b);return o.setState({canvas:e.current}),window.canvas=e.current,()=>{t(),e.current?.dispose(),n?.remove(),e.current=void 0,o.setState({canvas:null})}},[]),y(),u(()=>{const n=t=>{const{zoomable:P,maxManualZoom:f,minManualZoom:p,fitZoom:d=1,zoom:Y}=o.getState();if(t.e.preventDefault(),t.e.stopPropagation(),t.e.wheelDeltaY!==0){if(t.e.ctrlKey||t.e.wheelDeltaY===void 0){if(!P)return;const a=t.e.deltaY>0?.95:1.05;let r=Y/d*a;r>f&&(r=f),r<p&&(r=p);const v=r*d;e.current?.zoomToPoint(new w(t.e.offsetX,t.e.offsetY),v),o.setState({manualZoom:r,zoom:v})}else{const a=new w(-t.e.deltaX*1.5,-t.e.deltaY*1.5);e.current?.relativePan(a)}l?.(t)}};return e.current?.on("mouse:wheel",n),()=>{e.current?.off("mouse:wheel",n)}},[l,o]),u(()=>{o.setState({domNode:m.current?.closest(".react-fabric")})},[o]),u(()=>{e.current&&(e.current.set(s),e.current.requestRenderAll())},[s]),x("div",{className:"react-fabric__canvas",ref:m,style:j,children:[z("canvas",{ref:i}),h]})};export{N as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Canvas/index.tsx"],"sourcesContent":["import type { CanvasEvents, CanvasOptions, TPointerEventInfo } from 'fabric'\nimport { Canvas as BaseCanvas, Point } from 'fabric'\nimport type { CSSProperties, PropsWithChildren } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\nimport useDraggable from '../../hooks/useDraggable'\nimport useResizeHandler from '../../hooks/useResizeHandler'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllCanvasEvents } from '../../types/canvas'\nimport { bindEvents } from '../../utils/events'\n\nconst style: CSSProperties = {\n position: 'absolute',\n width: '100%',\n height: '100%',\n top: 0,\n left: 0,\n}\n\n// 首先定义事件类型\ntype CanvasEventProps = {\n [K in keyof AllCanvasEvents]: AllCanvasEvents[K]\n}\n\n// 分离配置属性类型\ntype CanvasConfigProps = Omit<CanvasOptions, keyof CanvasEventProps>\n\n// 重新定义 CanvasProps\nexport type CanvasProps = PropsWithChildren<Partial<CanvasConfigProps> & Partial<CanvasEventProps>>\n\nconst Canvas = ({ children, onMouseWheel, ...props }: CanvasProps) => {\n const canvasRef = useRef<BaseCanvas>()\n const store = useStoreApi()\n const canvasDomRef = useRef<HTMLCanvasElement | null>(null)\n useDraggable()\n const domRef = useRef<HTMLDivElement>(null)\n\n const [listeners, attributes] = useSplitProps(props)\n\n useLayoutEffect(() => {\n const canvas = canvasDomRef.current\n\n canvasRef.current = new BaseCanvas(canvas || undefined, {\n ...attributes,\n })\n\n // 绑定事件并获取清理函数\n const unbindEvents = bindEvents<CanvasEvents>(canvasRef.current, listeners)\n\n store.setState({\n canvas: canvasRef.current,\n })\n //@ts-expect-error\n window.canvas = canvasRef.current\n\n return () => {\n unbindEvents() // 调用清理函数\n canvasRef.current?.dispose()\n canvas?.remove()\n canvasRef.current = undefined // 清除引用\n store.setState({\n canvas: null,\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useResizeHandler()\n\n useEffect(() => {\n const onMouseWheelHandler = (opt: TPointerEventInfo<WheelEvent>) => {\n const { zoomable, maxManualZoom, minManualZoom, fitZoom = 1, zoom } = store.getState()\n\n // 阻止默认行为\n opt.e.preventDefault()\n opt.e.stopPropagation()\n\n // 如果是惯性滚动,直接返回\n if ((opt.e as any).wheelDeltaY === 0) return\n\n // 检查是否为缩放手势(Mac 上的双指捏合/张开)\n if (opt.e.ctrlKey || (opt.e as any).wheelDeltaY === undefined) {\n // 缩放逻辑\n if (!zoomable) return\n\n const delta = opt.e.deltaY\n const zoomFactor = delta > 0 ? 0.95 : 1.05\n let currentManualZoom = zoom / fitZoom\n let newManualZoom = currentManualZoom * zoomFactor\n\n if (newManualZoom > maxManualZoom) newManualZoom = maxManualZoom\n if (newManualZoom < minManualZoom) newManualZoom = minManualZoom\n\n const combinedZoom = newManualZoom * fitZoom\n\n canvasRef.current?.zoomToPoint(new Point(opt.e.offsetX, opt.e.offsetY), combinedZoom)\n\n store.setState({\n manualZoom: newManualZoom,\n zoom: combinedZoom,\n })\n } else {\n // 平移逻辑\n // 如果觉得太灵敏了,可以调小这个值,比如改为 1.2 或更小\n const sensitivityFactor = 1.5\n const delta = new Point(-opt.e.deltaX * sensitivityFactor, -opt.e.deltaY * sensitivityFactor)\n canvasRef.current?.relativePan(delta)\n }\n\n onMouseWheel?.(opt)\n }\n\n canvasRef.current?.on('mouse:wheel', onMouseWheelHandler)\n\n return () => {\n canvasRef.current?.off('mouse:wheel', onMouseWheelHandler)\n }\n }, [onMouseWheel, store])\n\n useEffect(() => {\n store.setState({\n domNode: domRef.current?.closest('.react-fabric') as HTMLDivElement,\n })\n }, [store])\n\n useEffect(() => {\n if (canvasRef.current) {\n canvasRef.current.set(attributes)\n canvasRef.current.requestRenderAll()\n }\n }, [attributes])\n\n return (\n <div className=\"react-fabric__canvas\" ref={domRef} style={style}>\n <canvas ref={canvasDomRef}></canvas>\n {children}\n </div>\n )\n}\n\nexport default Canvas\n"],"names":["style","Canvas","children","onMouseWheel","props","canvasRef","useRef","store","useStoreApi","canvasDomRef","useDraggable","domRef","listeners","attributes","useSplitProps","useLayoutEffect","canvas","BaseCanvas","unbindEvents","bindEvents","useResizeHandler","useEffect","onMouseWheelHandler","opt","zoomable","maxManualZoom","minManualZoom","fitZoom","zoom","zoomFactor","newManualZoom","combinedZoom","Point","delta","jsxs","jsx"],"mappings":"wbAWMA,EAAuB,CAC3B,SAAU,WACV,MAAO,OACP,OAAQ,OACR,IAAK,EACL,KAAM,CACR,EAaMC,EAAS,CAAC,CAAE,SAAAC,EAAU,aAAAC,EAAc,GAAGC,CAAM,IAAmB,CACpE,MAAMC,EAAYC,IACZC,EAAQC,EACRC,EAAAA,EAAeH,EAAiC,IAAI,EAC1DI,EACA,EAAA,MAAMC,EAASL,EAAuB,IAAI,EAEpC,CAACM,EAAWC,CAAU,EAAIC,EAAcV,CAAK,EAEnD,OAAAW,EAAgB,IAAM,CACpB,MAAMC,EAASP,EAAa,QAE5BJ,EAAU,QAAU,IAAIY,EAAWD,GAAU,OAAW,CACtD,GAAGH,CACL,CAAC,EAGD,MAAMK,EAAeC,EAAyBd,EAAU,QAASO,CAAS,EAE1E,OAAAL,EAAM,SAAS,CACb,OAAQF,EAAU,OACpB,CAAC,EAED,OAAO,OAASA,EAAU,QAEnB,IAAM,CACXa,EAAa,EACbb,EAAU,SAAS,QAAA,EACnBW,GAAQ,OACRX,EAAAA,EAAU,QAAU,OACpBE,EAAM,SAAS,CACb,OAAQ,IACV,CAAC,CACH,CAEF,EAAG,CAAE,CAAA,EAELa,EAEAC,EAAAA,EAAU,IAAM,CACd,MAAMC,EAAuBC,GAAuC,CAClE,KAAM,CAAE,SAAAC,EAAU,cAAAC,EAAe,cAAAC,EAAe,QAAAC,EAAU,EAAG,KAAAC,CAAK,EAAIrB,EAAM,SAAS,EAOrF,GAJAgB,EAAI,EAAE,eAAe,EACrBA,EAAI,EAAE,gBAAA,EAGDA,EAAI,EAAU,cAAgB,EAGnC,IAAIA,EAAI,EAAE,SAAYA,EAAI,EAAU,cAAgB,OAAW,CAE7D,GAAI,CAACC,EAAU,OAGf,MAAMK,EADQN,EAAI,EAAE,OACO,EAAI,IAAO,KAEtC,IAAIO,EADoBF,EAAOD,EACSE,EAEpCC,EAAgBL,IAAeK,EAAgBL,GAC/CK,EAAgBJ,IAAeI,EAAgBJ,GAEnD,MAAMK,EAAeD,EAAgBH,EAErCtB,EAAU,SAAS,YAAY,IAAI2B,EAAMT,EAAI,EAAE,QAASA,EAAI,EAAE,OAAO,EAAGQ,CAAY,EAEpFxB,EAAM,SAAS,CACb,WAAYuB,EACZ,KAAMC,CACR,CAAC,CACH,KAAO,CAIL,MAAME,EAAQ,IAAID,EAAM,CAACT,EAAI,EAAE,OAAS,IAAmB,CAACA,EAAI,EAAE,OAAS,GAAiB,EAC5FlB,EAAU,SAAS,YAAY4B,CAAK,CACtC,CAEA9B,IAAeoB,CAAG,CACpB,CAAA,EAEA,OAAAlB,EAAU,SAAS,GAAG,cAAeiB,CAAmB,EAEjD,IAAM,CACXjB,EAAU,SAAS,IAAI,cAAeiB,CAAmB,CAC3D,CACF,EAAG,CAACnB,EAAcI,CAAK,CAAC,EAExBc,EAAU,IAAM,CACdd,EAAM,SAAS,CACb,QAASI,EAAO,SAAS,QAAQ,eAAe,CAClD,CAAC,CACH,EAAG,CAACJ,CAAK,CAAC,EAEVc,EAAU,IAAM,CACVhB,EAAU,UACZA,EAAU,QAAQ,IAAIQ,CAAU,EAChCR,EAAU,QAAQ,iBAEtB,EAAA,EAAG,CAACQ,CAAU,CAAC,EAGbqB,EAAC,OAAI,UAAU,uBAAuB,IAAKvB,EAAQ,MAAOX,EACxD,SAAAmC,CAAAA,EAAC,UAAO,IAAK1B,CAAAA,CAAc,EAC1BP,CACH,CAAA,CAAA,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsxs as b,Fragment as P,jsx as O}from"react/jsx-runtime";import{computePosition as j,offset as k,flip as D,shift as F}from"@floating-ui/core";import{util as M}from"fabric";import{twMerge as q}from"tailwind-merge";import l,{useRef as w,useCallback as x,useMemo as A,useEffect as p}from"react";import{useStore as B}from"../../hooks/useStore.mjs";import L from"../NodeToolbarPortal/index.mjs";const N=l.forwardRef(({children:a,className:C,placement:d="bottom",open:o=!0,onOpenChange:f,closeOnOutsideClick:g=!0,Content:v},u)=>{const c=w(void 0),t=B(e=>e.canvas),r=w(null),h=x(e=>{e!==c.current&&(c.current=e,typeof u=="function"?u(e):u&&(u.current=e))},[u]),y=A(()=>l.Children.only(a)&&l.isValidElement(a)?l.cloneElement(a,{ref:h,...a.props}):a,[a,h]),m=x(()=>{if(!c.current||!r.current||!t)return;const e=r.current.getBoundingClientRect();if(e.width===0||e.height===0){requestAnimationFrame(m);return}const n=c.current.getCoords().map(s=>M.sendPointToPlane(s,t.viewportTransform,void 0)),i={getElementRects:s=>s,getDimensions:s=>s,getClippingRect:()=>({x:0,y:0,width:t.width,height:t.height})},E={x:n[0].x,y:n[0].y,width:n[2].x-n[0].x,height:n[2].y-n[0].y};j(E,r.current.getBoundingClientRect(),{platform:i,placement:d,middleware:[k(5),D(),F({padding:5})]}).then(({x:s,y:R})=>{r.current&&Object.assign(r.current.style,{left:`${s}px`,top:`${R}px`})})},[t,d]);return p(()=>{o&&requestAnimationFrame(m)},[o,m]),p(()=>(t?.on("after:render",m),()=>{t?.off("after:render",m)}),[t,m]),p(()=>{const e=i=>{i.e.stopPropagation(),i.e.preventDefault(),i.target===c.current?f?.(!o):o&&f?.(!1)},n=i=>{r.current?.contains(i.target)||g&&o&&f?.(!1)};return t?.on("mouse:down",e),document.addEventListener("mousedown",n,!1),()=>{t?.off("mouse:down",e),document.removeEventListener("mousedown",n,!1)}},[t,g,f,o]),b(P,{children:[y,o&&O(L,{className:q("absolute",C),ref:r,onClick:e=>{e.stopPropagation(),e.preventDefault()},children:v})]})});export{N as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Control/index.tsx"],"sourcesContent":["import { computePosition, flip, offset, shift,ComputePositionConfig } from '@floating-ui/core'\nimport type { FabricObject, FabricObjectProps, TPointerEvent, TPointerEventInfo } from 'fabric'\nimport { util } from 'fabric'\nimport { twMerge } from 'tailwind-merge'\nimport type { ReactNode } from 'react'\nimport { useMemo } from 'react'\nimport { useCallback } from 'react'\nimport { useRef } from 'react'\nimport { useEffect } from 'react'\nimport React from 'react'\nimport { useStore } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport NodeToolbarPortal from '../NodeToolbarPortal'\n\n/**\n * @desc 不能内置支持 selected , 因为需要 rect 开启 lockMovementX lockMovementY, 这样支持的场景就受限了\n */\nexport type ControlProps = Partial<AllObjectEvents & FabricObjectProps> & {\n Content: ReactNode\n children: ReactNode\n placement?: ComputePositionConfig['placement']\n className?: string\n open?: boolean\n onOpenChange?: (open: boolean) => void\n closeOnOutsideClick?: boolean\n}\n\nconst Control = React.forwardRef(\n (\n {\n children,\n className,\n placement = 'bottom',\n open = true,\n onOpenChange,\n closeOnOutsideClick = true,\n Content,\n }: ControlProps,\n forwardRef,\n ) => {\n const instanceRef = useRef<FabricObject | undefined>(undefined)\n const canvas = useStore(state => state.canvas)\n const floatingElRef = useRef<HTMLDivElement>(null)\n\n // 使用 useCallback 创建稳定的 ref 回调\n const refCallback = useCallback(\n (node: any) => {\n // 只在节点真正改变时更新 ref\n if (node !== instanceRef.current) {\n instanceRef.current = node\n\n // 处理 forwardRef\n if (typeof forwardRef === 'function') {\n forwardRef(node)\n } else if (forwardRef) {\n forwardRef.current = node\n }\n }\n },\n [forwardRef],\n )\n\n // 使用 useMemo 缓存克隆的子元素\n const newChildren = useMemo(() => {\n if (React.Children.only(children) && React.isValidElement(children)) {\n return React.cloneElement(children, {\n ref: refCallback,\n ...children.props,\n })\n }\n return children\n }, [children, refCallback]) // 只在 children 或 refCallback 改变时重新克隆\n\n const updatePosition = useCallback(() => {\n if (!instanceRef.current || !floatingElRef.current || !canvas) {\n return\n }\n\n // 确保元素已经渲染并且有尺寸\n const floatingRect = floatingElRef.current.getBoundingClientRect()\n if (floatingRect.width === 0 || floatingRect.height === 0) {\n // 如果元素还没有尺寸,等待下一帧再试\n requestAnimationFrame(updatePosition)\n return\n }\n\n const sceneCoords = instanceRef.current.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const platform = {\n getElementRects: (data:any) => data,\n getDimensions: (element:any) => element,\n getClippingRect: () => ({\n x: 0,\n y: 0,\n width: canvas.width,\n height: canvas.height,\n }),\n }\n\n const virtualEl = {\n x: viewportCoords[0].x,\n y: viewportCoords[0].y,\n width: viewportCoords[2].x - viewportCoords[0].x,\n height: viewportCoords[2].y - viewportCoords[0].y,\n }\n\n computePosition(virtualEl, floatingElRef.current.getBoundingClientRect(), {\n platform,\n placement,\n middleware: [offset(5), flip(), shift({ padding: 5 })],\n }).then(({ x, y }) => {\n if (!floatingElRef.current) return\n\n Object.assign(floatingElRef.current.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n }, [canvas, placement])\n\n // 确保在元素挂载后更新位置\n useEffect(() => {\n if (open) {\n requestAnimationFrame(updatePosition)\n }\n }, [open, updatePosition])\n\n useEffect(() => {\n canvas?.on('after:render', updatePosition)\n\n return () => {\n canvas?.off('after:render', updatePosition)\n }\n }, [canvas, updatePosition])\n\n useEffect(() => {\n const handleCanvasClick = (e: TPointerEventInfo<TPointerEvent>) => {\n // 阻止事件冒泡到 document\n e.e.stopPropagation()\n e.e.preventDefault() // 也阻止默认行为\n\n // 使用 id 比较来确保正确匹配\n if (e.target === instanceRef.current) {\n onOpenChange?.(!open)\n }\n // 点击其他区域时关闭\n else if (open) {\n onOpenChange?.(false)\n }\n }\n\n const handleDocumentClick = (e: MouseEvent) => {\n // 如果点击在浮动内容内,不处理\n if (floatingElRef.current?.contains(e.target as Node)) {\n return\n }\n\n if (closeOnOutsideClick && open) {\n onOpenChange?.(false)\n }\n }\n\n canvas?.on('mouse:down', handleCanvasClick)\n // 改为冒泡阶段处理 document 事件\n document.addEventListener('mousedown', handleDocumentClick, false)\n\n return () => {\n canvas?.off('mouse:down', handleCanvasClick)\n document.removeEventListener('mousedown', handleDocumentClick, false)\n }\n }, [canvas, closeOnOutsideClick, onOpenChange, open])\n\n return (\n <>\n {newChildren}\n {open && (\n <NodeToolbarPortal\n className={twMerge('absolute', className)}\n ref={floatingElRef}\n onClick={e => {\n e.stopPropagation()\n e.preventDefault()\n }}\n >\n {Content}\n </NodeToolbarPortal>\n )}\n </>\n )\n },\n)\n\nexport default Control\n"],"names":["Control","React","children","className","placement","open","onOpenChange","closeOnOutsideClick","Content","forwardRef","instanceRef","useRef","canvas","useStore","state","floatingElRef","refCallback","useCallback","node","newChildren","useMemo","updatePosition","floatingRect","viewportCoords","point","util","platform","data","element","virtualEl","computePosition","offset","flip","shift","x","y","useEffect","handleCanvasClick","e","handleDocumentClick","jsxs","Fragment","jsx","NodeToolbarPortal","twMerge"],"mappings":"0ZA2BA,MAAMA,EAAUC,EAAM,WACpB,CACE,CACE,SAAAC,EACA,UAAAC,EACA,UAAAC,EAAY,SACZ,KAAAC,EAAO,GACP,aAAAC,EACA,oBAAAC,EAAsB,GACtB,QAAAC,CACF,EACAC,IACG,CACH,MAAMC,EAAcC,EAAiC,MAAS,EACxDC,EAASC,EAASC,GAASA,EAAM,MAAM,EACvCC,EAAgBJ,EAAuB,IAAI,EAG3CK,EAAcC,EACjBC,GAAc,CAETA,IAASR,EAAY,UACvBA,EAAY,QAAUQ,EAGlB,OAAOT,GAAe,WACxBA,EAAWS,CAAI,EACNT,IACTA,EAAW,QAAUS,GAG3B,EACA,CAACT,CAAU,CACb,EAGMU,EAAcC,EAAQ,IACtBnB,EAAM,SAAS,KAAKC,CAAQ,GAAKD,EAAM,eAAeC,CAAQ,EACzDD,EAAM,aAAaC,EAAU,CAClC,IAAKc,EACL,GAAGd,EAAS,KACd,CAAC,EAEIA,EACN,CAACA,EAAUc,CAAW,CAAC,EAEpBK,EAAiBJ,EAAY,IAAM,CACvC,GAAI,CAACP,EAAY,SAAW,CAACK,EAAc,SAAW,CAACH,EACrD,OAIF,MAAMU,EAAeP,EAAc,QAAQ,sBAAsB,EACjE,GAAIO,EAAa,QAAU,GAAKA,EAAa,SAAW,EAAG,CAEzD,sBAAsBD,CAAc,EACpC,MACF,CAGA,MAAME,EADcb,EAAY,QAAQ,YACL,IAAIc,GAASC,EAAK,iBAAiBD,EAAOZ,EAAO,kBAAmB,MAAS,CAAC,EAE3Gc,EAAW,CACf,gBAAkBC,GAAaA,EAC/B,cAAgBC,GAAgBA,EAChC,gBAAiB,KAAO,CACtB,EAAG,EACH,EAAG,EACH,MAAOhB,EAAO,MACd,OAAQA,EAAO,MACjB,EACF,EAEMiB,EAAY,CAChB,EAAGN,EAAe,CAAC,EAAE,EACrB,EAAGA,EAAe,CAAC,EAAE,EACrB,MAAOA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,EAC/C,OAAQA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAClD,EAEAO,EAAgBD,EAAWd,EAAc,QAAQ,wBAAyB,CACxE,SAAAW,EACA,UAAAtB,EACA,WAAY,CAAC2B,EAAO,CAAC,EAAGC,EAAK,EAAGC,EAAM,CAAE,QAAS,CAAE,CAAC,CAAC,CACvD,CAAC,EAAE,KAAK,CAAC,CAAE,EAAAC,EAAG,EAAAC,CAAE,IAAM,CACfpB,EAAc,SAEnB,OAAO,OAAOA,EAAc,QAAQ,MAAO,CACzC,KAAM,GAAGmB,CAAC,KACV,IAAK,GAAGC,CAAC,IACX,CAAC,CACH,CAAC,CACH,EAAG,CAACvB,EAAQR,CAAS,CAAC,EAGtB,OAAAgC,EAAU,IAAM,CACV/B,GACF,sBAAsBgB,CAAc,CAExC,EAAG,CAAChB,EAAMgB,CAAc,CAAC,EAEzBe,EAAU,KACRxB,GAAQ,GAAG,eAAgBS,CAAc,EAElC,IAAM,CACXT,GAAQ,IAAI,eAAgBS,CAAc,CAC5C,GACC,CAACT,EAAQS,CAAc,CAAC,EAE3Be,EAAU,IAAM,CACd,MAAMC,EAAqBC,GAAwC,CAEjEA,EAAE,EAAE,kBACJA,EAAE,EAAE,iBAGAA,EAAE,SAAW5B,EAAY,QAC3BJ,IAAe,CAACD,CAAI,EAGbA,GACPC,IAAe,EAAK,CAExB,EAEMiC,EAAuBD,GAAkB,CAEzCvB,EAAc,SAAS,SAASuB,EAAE,MAAc,GAIhD/B,GAAuBF,GACzBC,IAAe,EAAK,CAExB,EAEA,OAAAM,GAAQ,GAAG,aAAcyB,CAAiB,EAE1C,SAAS,iBAAiB,YAAaE,EAAqB,EAAK,EAE1D,IAAM,CACX3B,GAAQ,IAAI,aAAcyB,CAAiB,EAC3C,SAAS,oBAAoB,YAAaE,EAAqB,EAAK,CACtE,CACF,EAAG,CAAC3B,EAAQL,EAAqBD,EAAcD,CAAI,CAAC,EAGlDmC,EAAAC,EAAA,CACG,SAAAtB,CAAAA,EACAd,GACCqC,EAACC,EAAA,CACC,UAAWC,EAAQ,WAAYzC,CAAS,EACxC,IAAKY,EACL,QAASuB,GAAK,CACZA,EAAE,gBAAgB,EAClBA,EAAE,eACJ,CAAA,EAEC,SAAA9B,CAAAA,CACH,CAEJ,CAAA,CAAA,CAEJ,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{Ellipse as p}from"fabric";import{forwardRef as i,useImperativeHandle as m,memo as a}from"react";import{useCreateObject as n}from"../../hooks/useCreateObject.mjs";import{useSplitProps as f}from"../../hooks/useSplitProps.mjs";const d=i(({group:r,...t},o)=>{const[s,u,l]=f(t),e=n({Constructor:p,defaultValues:l,attributes:u,group:r,listeners:s});return m(o,()=>e,[e]),null});var c=a(d);export{c as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Ellipse/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { Ellipse as BaseEllipse } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\n\nexport type EllipseProps<T = unknown> = Partial<BaseEllipse & AllObjectEvents> & {\n group?: BaseGroup\n defaultLeft?: number\n defaultTop?: number\n defaultWidth?: number\n defaultHeight?: number\n} & T\n\nconst Ellipse = forwardRef<BaseEllipse | undefined, EllipseProps>(({ group, ...props }, ref) => {\n const [listeners, attributes, defaultValues] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: BaseEllipse,\n defaultValues,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return null\n})\n\nexport default memo(Ellipse)\n"],"names":["Ellipse","forwardRef","group","props","ref","listeners","attributes","defaultValues","useSplitProps","instance","useCreateObject","BaseEllipse","useImperativeHandle","memo"],"mappings":"oPAeA,MAAMA,EAAUC,EAAkD,CAAC,CAAE,MAAAC,EAAO,GAAGC,CAAM,EAAGC,IAAQ,CAC9F,KAAM,CAACC,EAAWC,EAAYC,CAAa,EAAIC,EAAcL,CAAK,EAE5DM,EAAWC,EAAgB,CAC/B,YAAaC,EACb,cAAAJ,EACA,WAAAD,EACA,MAAAJ,EACA,UAAAG,CACF,CAAC,EAED,OAAAO,EAAoBR,EAAK,IAAMK,EAAU,CAACA,CAAQ,CAAC,EAE5C,IACT,CAAC,EAED,MAAeI,EAAKb,CAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as c,Fragment as p}from"react/jsx-runtime";import{Group as d}from"fabric";import{memo as f,useState as S,useLayoutEffect as v,useEffect as n,Children as g,isValidElement as E,cloneElement as b}from"react";import{useDidUpdate as h}from"../../hooks/useDidUpdate.mjs";import{useSplitProps as y}from"../../hooks/useSplitProps.mjs";import{useStoreApi as C}from"../../hooks/useStore.mjs";import{bindEvents as V}from"../../utils/events.mjs";const x=f(({children:a,controlsVisibility:r,...u})=>{const o=C(),[t,i]=S(null),[l,s]=y(u);return v(()=>{const e=new d([],{...s});return i(e),()=>{const{canvas:m}=o.getState();e&&m&&m.remove(e),i(null)}},[o]),n(()=>{const{canvas:e}=o.getState();!t||!e||e.add(t)},[o,t]),n(()=>t?V(t,l):void 0,[t,l]),n(()=>{!t||!r||t.setControlsVisibility(r)},[t,r]),h(()=>{const{canvas:e}=o.getState();!t||!e||(t.set(s),t.setCoords(),e.requestRenderAll())},[s]),c(p,{children:t&&g.map(a,e=>E(e)?b(e,{group:t}):null)})});export{x as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Group/index.tsx"],"sourcesContent":["import type { GroupEvents, GroupProps } from 'fabric'\nimport { Group as BaseGroup } from 'fabric'\nimport { Children, cloneElement, isValidElement, memo, useEffect, useLayoutEffect, useState } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllEvents } from '../../types/canvas'\nimport { bindEvents } from '../../utils/events'\n\nexport type MyGroupProps = Partial<GroupProps & AllEvents<GroupEvents>> & {\n children: React.ReactElement<{ group?: BaseGroup }>[] | React.ReactElement<{ group?: BaseGroup }>\n controlsVisibility?: {\n ml?: boolean\n mt?: boolean\n mr?: boolean\n mb?: boolean\n mtr?: boolean\n tl?: boolean\n tr?: boolean\n bl?: boolean\n br?: boolean\n }\n}\n\nconst Group = memo(({ children, controlsVisibility, ...props }: MyGroupProps) => {\n const store = useStoreApi()\n const [instance, setInstance] = useState<BaseGroup | null>(null)\n\n const [listeners, attributes] = useSplitProps(props)\n\n // 创建 Group 实例,但不立即添加到 canvas\n useLayoutEffect(() => {\n const newInstance = new BaseGroup([], {\n ...attributes,\n })\n setInstance(newInstance)\n\n return () => {\n const { canvas } = store.getState()\n if (newInstance && canvas) {\n canvas.remove(newInstance)\n }\n setInstance(null)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store])\n\n // 等待子元素添加完成后,再将 group 添加到 canvas\n useEffect(() => {\n const { canvas } = store.getState()\n if (!instance || !canvas) return\n\n canvas.add(instance)\n }, [store, instance])\n\n // 单独处理事件绑定\n useEffect(() => {\n if (!instance) return\n\n const cleanup = bindEvents(instance, listeners)\n return cleanup\n }, [instance, listeners])\n\n // 专门处理 setControlsVisibility\n useEffect(() => {\n if (!instance || !controlsVisibility) return\n instance.setControlsVisibility(controlsVisibility)\n }, [instance, controlsVisibility])\n\n // 处理属性更新\n useDidUpdate(() => {\n const { canvas } = store.getState()\n if (!instance || !canvas) return\n\n instance.set(attributes)\n instance.setCoords()\n canvas.requestRenderAll()\n }, [attributes])\n\n return (\n <>\n {instance &&\n Children.map(children, child => {\n if (isValidElement(child)) {\n return cloneElement(child, {\n group: instance,\n })\n }\n return null\n })}\n </>\n )\n})\n\nexport default Group\n"],"names":["Group","memo","children","controlsVisibility","props","store","useStoreApi","instance","setInstance","useState","listeners","attributes","useSplitProps","useLayoutEffect","newInstance","BaseGroup","canvas","useEffect","bindEvents","useDidUpdate","jsx","Fragment","Children","child","isValidElement","cloneElement"],"mappings":"gdAwBMA,EAAQC,EAAK,CAAC,CAAE,SAAAC,EAAU,mBAAAC,EAAoB,GAAGC,CAAM,IAAoB,CAC/E,MAAMC,EAAQC,IACR,CAACC,EAAUC,CAAW,EAAIC,EAA2B,IAAI,EAEzD,CAACC,EAAWC,CAAU,EAAIC,EAAcR,CAAK,EAGnD,OAAAS,EAAgB,IAAM,CACpB,MAAMC,EAAc,IAAIC,EAAU,CAAA,EAAI,CACpC,GAAGJ,CACL,CAAC,EACD,OAAAH,EAAYM,CAAW,EAEhB,IAAM,CACX,KAAM,CAAE,OAAAE,CAAO,EAAIX,EAAM,SAAS,EAC9BS,GAAeE,GACjBA,EAAO,OAAOF,CAAW,EAE3BN,EAAY,IAAI,CAClB,CAEF,EAAG,CAACH,CAAK,CAAC,EAGVY,EAAU,IAAM,CACd,KAAM,CAAE,OAAAD,CAAO,EAAIX,EAAM,SAAS,EAC9B,CAACE,GAAY,CAACS,GAElBA,EAAO,IAAIT,CAAQ,CACrB,EAAG,CAACF,EAAOE,CAAQ,CAAC,EAGpBU,EAAU,IACHV,EAEWW,EAAWX,EAAUG,CAAS,EAF/B,OAId,CAACH,EAAUG,CAAS,CAAC,EAGxBO,EAAU,IAAM,CACV,CAACV,GAAY,CAACJ,GAClBI,EAAS,sBAAsBJ,CAAkB,CACnD,EAAG,CAACI,EAAUJ,CAAkB,CAAC,EAGjCgB,EAAa,IAAM,CACjB,KAAM,CAAE,OAAAH,CAAO,EAAIX,EAAM,SAAS,EAC9B,CAACE,GAAY,CAACS,IAElBT,EAAS,IAAII,CAAU,EACvBJ,EAAS,UACTS,EAAAA,EAAO,iBAAiB,EAC1B,EAAG,CAACL,CAAU,CAAC,EAGbS,EAAAC,EAAA,CACG,SAAAd,GACCe,EAAS,IAAIpB,EAAUqB,GACjBC,EAAeD,CAAK,EACfE,EAAaF,EAAO,CACzB,MAAOhB,CACT,CAAC,EAEI,IACR,CACL,CAAA,CAEJ,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{Line as n}from"fabric";import{forwardRef as f,useImperativeHandle as l,memo as c}from"react";import{useCreateObject as b}from"../../hooks/useCreateObject.mjs";import{useSplitProps as d}from"../../hooks/useSplitProps.mjs";const x=f(({group:e,x1:t,y1:o,x2:m,y2:s,...i},p)=>{const[u,a]=d(i),r=b({Constructor:n,param:[t,o,m,s],attributes:a,group:e,listeners:u});return l(p,()=>r,[r]),null});var g=c(x);export{g as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Line/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { Line as BaseLine } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\n\nexport type Handle = BaseLine | undefined\n\nexport type LineProps<T = unknown> = Partial<ConstructorParameters<typeof BaseLine>[1] & AllObjectEvents> & {\n group?: BaseGroup\n path?: string\n} & T\n\nconst Line = forwardRef<Handle, LineProps>(({ group, x1, y1, x2, y2, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: BaseLine,\n param: [x1, y1, x2, y2],\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return null\n})\n\nexport default memo(Line)\n"],"names":["Line","forwardRef","group","x1","y1","x2","y2","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","BaseLine","useImperativeHandle","memo"],"mappings":"iPAcA,MAAMA,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,GAAGC,CAAM,EAAGC,IAAQ,CACvF,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAaC,EACb,MAAO,CAACX,EAAIC,EAAIC,EAAIC,CAAE,EACtB,WAAAI,EACA,MAAAR,EACA,UAAAO,CACF,CAAC,EAED,OAAAM,EAAoBP,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5C,IACT,CAAC,EAED,IAAeI,EAAAA,EAAKhB,CAAI"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsxs as o,jsx as e}from"react/jsx-runtime";import{LoadingOutlined as s}from"@ant-design/icons";import{useStore as l}from"../../hooks/useStore.mjs";const i=()=>l(t=>t.loading)?o("div",{className:"absolute inset-0 z-[40] flex flex-col items-center justify-center overflow-hidden",children:[e("div",{className:"absolute bottom-0 left-0 right-0 top-0 ]"}),e(s,{spin:!0,className:"text-lg text-[var(--color-primary)]"})]}):null;export{i as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Loading/index.tsx"],"sourcesContent":["import { LoadingOutlined } from '@ant-design/icons'\nimport { useStore } from '../../hooks/useStore'\n\n// bg-[hsla(221,14%,4%,0.6)\nconst Loading = () => {\n const loading = useStore(state => state.loading)\n\n return loading ? (\n <div className=\"absolute inset-0 z-[40] flex flex-col items-center justify-center overflow-hidden\">\n <div className=\"absolute bottom-0 left-0 right-0 top-0 ]\"></div>\n <LoadingOutlined spin className=\"text-lg text-[var(--color-primary)]\" />\n </div>\n ) : null\n}\n\nexport default Loading\n"],"names":["Loading","useStore","state","jsxs","jsx","LoadingOutlined"],"mappings":"uKAIA,MAAMA,EAAU,IACEC,EAASC,GAASA,EAAM,OAAO,EAG7CC,EAAC,OAAI,UAAU,oFACb,UAAAC,EAAC,MAAA,CAAI,UAAU,0CAA2C,CAAA,EAC1DA,EAACC,EAAA,CAAgB,KAAI,GAAC,UAAU,sCAAsC,CACxE,CAAA,CAAA,EACE"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{createPortal as u}from"react-dom";import{twMerge as l}from"tailwind-merge";import{forwardRef as f,useRef as m,useCallback as d,useEffect as p}from"react";import{useStore as v}from"../../hooks/useStore.mjs";const b=o=>o.domNode?.querySelector(".react-fabric__canvas"),E=f(({children:o,className:i,onClick:n},t)=>{const a=v(b),e=m(),s=d(r=>{r!==e.current&&(e.current=r||void 0,typeof t=="function"?t(r):t&&(t.current=r))},[t]);if(p(()=>()=>{e.current&&(e.current.remove(),e.current=void 0)},[]),!a||e.current)return e.current?u(o,e.current):null;const c=document.createElement("div");return c.className=l("react-fabric__portal",i),n&&c.addEventListener("click",r=>{r.stopPropagation(),n(r)}),a.appendChild(c),s(c),u(o,c)});export{E as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/NodeToolbarPortal/index.tsx"],"sourcesContent":["import { createPortal } from 'react-dom'\nimport { twMerge } from 'tailwind-merge'\nimport type { ReactNode } from 'react'\nimport { forwardRef, useCallback, useEffect, useRef } from 'react'\nimport { useStore } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nconst selector = (state: ReactFabricState) => state.domNode?.querySelector('.react-fabric__canvas')\n\ninterface Props {\n children: ReactNode\n className?: string\n onClick?: (e: React.MouseEvent) => void\n}\n\nconst NodeToolbarPortal = forwardRef<HTMLDivElement, Props>(({ children, className, onClick }, forwardRef) => {\n const wrapperRef = useStore(selector)\n const containerRef = useRef<HTMLDivElement>()\n\n // 使用 useCallback 创建稳定的 ref 回调\n const refCallback = useCallback(\n (node: HTMLDivElement | null) => {\n if (node !== containerRef.current) {\n containerRef.current = node || undefined\n\n if (typeof forwardRef === 'function') {\n forwardRef(node)\n } else if (forwardRef) {\n forwardRef.current = node\n }\n }\n },\n [forwardRef],\n )\n\n // 组件卸载时清理\n useEffect(() => {\n return () => {\n if (containerRef.current) {\n containerRef.current.remove()\n containerRef.current = undefined\n }\n }\n }, [])\n\n // 如果已经有 container 或没有 wrapper,直接返回\n if (!wrapperRef || containerRef.current) {\n return containerRef.current ? createPortal(children, containerRef.current) : null\n }\n\n // 创建 DOM 元素\n const div = document.createElement('div')\n div.className = twMerge('react-fabric__portal', className)\n if (onClick) {\n div.addEventListener('click', e => {\n e.stopPropagation()\n onClick(e as any)\n })\n }\n wrapperRef.appendChild(div)\n refCallback(div)\n\n return createPortal(children, div)\n})\n\nexport default NodeToolbarPortal\n"],"names":["selector","state","NodeToolbarPortal","forwardRef","children","className","onClick","wrapperRef","useStore","containerRef","useRef","refCallback","useCallback","node","useEffect","createPortal","div","twMerge","e"],"mappings":"kOAOA,MAAMA,EAAYC,GAA4BA,EAAM,SAAS,cAAc,uBAAuB,EAQ5FC,EAAoBC,EAAkC,CAAC,CAAE,SAAAC,EAAU,UAAAC,EAAW,QAAAC,CAAQ,EAAGH,IAAe,CAC5G,MAAMI,EAAaC,EAASR,CAAQ,EAC9BS,EAAeC,EAAAA,EAGfC,EAAcC,EACjBC,GAAgC,CAC3BA,IAASJ,EAAa,UACxBA,EAAa,QAAUI,GAAQ,OAE3B,OAAOV,GAAe,WACxBA,EAAWU,CAAI,EACNV,IACTA,EAAW,QAAUU,GAG3B,EACA,CAACV,CAAU,CACb,EAaA,GAVAW,EAAU,IACD,IAAM,CACPL,EAAa,UACfA,EAAa,QAAQ,SACrBA,EAAa,QAAU,OAE3B,EACC,CAAA,CAAE,EAGD,CAACF,GAAcE,EAAa,QAC9B,OAAOA,EAAa,QAAUM,EAAaX,EAAUK,EAAa,OAAO,EAAI,KAI/E,MAAMO,EAAM,SAAS,cAAc,KAAK,EACxC,OAAAA,EAAI,UAAYC,EAAQ,uBAAwBZ,CAAS,EACrDC,GACFU,EAAI,iBAAiB,QAASE,GAAK,CACjCA,EAAE,gBACFZ,EAAAA,EAAQY,CAAQ,CAClB,CAAC,EAEHX,EAAW,YAAYS,CAAG,EAC1BL,EAAYK,CAAG,EAERD,EAAaX,EAAUY,CAAG,CACnC,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as o,Fragment as p}from"react/jsx-runtime";import{memo as l}from"react";import s from"../Path/index.mjs";import e from"../Text/index.mjs";import c from"../Rect/index.mjs";import f from"../Line/index.mjs";const a=({objects:r})=>{const m={rect:c,path:s,text:e,line:f,"i-text":e};return r?o(p,{children:r?.map(({type:n,...i})=>{const t=m[n.toLowerCase()];return t?o(t,{...i}):null})}):null};var u=l(a);export{u as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Objects/index.tsx"],"sourcesContent":["import { memo } from 'react'\nimport Path from '../Path'\nimport Text from '../Text'\nimport Rect from '../Rect'\nimport Line from '../Line'\n\nexport type ObjectsProps = {\n objects: { type: string; [index: string]: any }[]\n}\n\nconst Objects = ({ objects }: ObjectsProps) => {\n const components = {\n rect: Rect,\n path: Path,\n text: Text,\n line: Line,\n 'i-text': Text,\n }\n\n if (!objects) return null\n return (\n <>\n {objects?.map(({ type, ...options }) => {\n // @ts-expect-error\n const Component = components[type.toLowerCase()]\n if (!Component) {\n \n return null\n }\n return <Component {...options} />\n })}\n </>\n )\n}\n\nexport default memo(Objects)\n"],"names":["Objects","objects","components","Rect","Path","Text","Line","jsx","Fragment","type","options","Component","memo"],"mappings":"oOAUA,MAAMA,EAAU,CAAC,CAAE,QAAAC,CAAQ,IAAoB,CAC7C,MAAMC,EAAa,CACjB,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,SAAUD,CACZ,EAEA,OAAKJ,EAEHM,EAAAC,EAAA,CACG,SAAAP,GAAS,IAAI,CAAC,CAAE,KAAAQ,EAAM,GAAGC,CAAQ,IAAM,CAEtC,MAAMC,EAAYT,EAAWO,EAAK,YAAA,CAAa,EAC/C,OAAKE,EAIEJ,EAACI,EAAA,CAAW,GAAGD,CAAAA,CAAS,EAFtB,IAGX,CAAC,CACH,CAAA,EAZmB,IAcvB,EAEA,IAAeE,EAAAA,EAAKZ,CAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{Path as m}from"fabric";import{forwardRef as u,useImperativeHandle as i,memo as n}from"react";import{useCreateObject as f}from"../../hooks/useCreateObject.mjs";import{useSplitProps as l}from"../../hooks/useSplitProps.mjs";const c=u(({group:t,path:e="M 0 0",...o},s)=>{const[p,a]=l(o),r=f({Constructor:m,param:e,attributes:a,group:t,listeners:p});return i(s,()=>r,[r]),null});var d=n(c);export{d as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Path/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { Path as BasePath } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\n\nexport type Handle = BasePath | undefined\n\nexport type PathProps<T = unknown> = Partial<ConstructorParameters<typeof BasePath>[1] & AllObjectEvents> & {\n group?: BaseGroup\n path?: string\n} & T\n\nconst Path = forwardRef<Handle, PathProps>(({ group, path = 'M 0 0', ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: BasePath,\n param: path,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return null\n})\n\nexport default memo(Path)\n"],"names":["Path","forwardRef","group","path","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","BasePath","useImperativeHandle","memo"],"mappings":"iPAcA,MAAMA,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAO,QAAS,GAAGC,CAAM,EAAGC,IAAQ,CACvF,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAaC,EACb,MAAOR,EACP,WAAAI,EACA,MAAAL,EACA,UAAAI,CACF,CAAC,EAED,OAAAM,EAAoBP,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5C,IACT,CAAC,EAED,MAAeI,EAAKb,CAAI"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as a}from"react/jsx-runtime";import{useState as n}from"react";import{Provider as l}from"../contexts/StoreContext.mjs";import{createStore as s}from"../store/index.mjs";function c({initialNodes:i,defaultNodes:e,initialWidth:t,initialHeight:r,children:o}){const[d]=n(()=>s({nodes:i,defaultNodes:e,width:t,height:r}));return a(l,{value:d,children:o})}export{c as ReactFabricProvider};
|
|
2
|
+
//# sourceMappingURL=ReactFabricProvider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReactFabricProvider.mjs","sources":["../../../src/components/ReactFabricProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { useState } from 'react'\nimport { Provider } from '../contexts/StoreContext'\nimport { createStore } from '../store'\nimport type { Node } from '../types/nodes'\n\nexport type ReactFabricProviderProps = {\n initialNodes?: Node[]\n defaultNodes?: Node[]\n initialWidth?: number\n initialHeight?: number\n children: ReactNode\n}\nexport function ReactFabricProvider({\n initialNodes: nodes,\n defaultNodes,\n initialWidth: width,\n initialHeight: height,\n children,\n}: ReactFabricProviderProps) {\n const [store] = useState(() =>\n createStore({\n nodes,\n defaultNodes,\n width,\n height,\n }),\n )\n\n return <Provider value={store}>{children}</Provider>\n}\n"],"names":["ReactFabricProvider","nodes","defaultNodes","width","height","children","store","useState","createStore","jsx","Provider"],"mappings":"+LAagB,SAAAA,EAAoB,CAClC,aAAcC,EACd,aAAAC,EACA,aAAcC,EACd,cAAeC,EACf,SAAAC,CACF,EAA6B,CAC3B,KAAM,CAACC,CAAK,EAAIC,EAAS,IACvBC,EAAY,CACV,MAAAP,EACA,aAAAC,EACA,MAAAC,EACA,OAAAC,CACF,CAAC,CACH,EAEA,OAAOK,EAACC,EAAA,CAAS,MAAOJ,EAAQ,SAAAD,CAAAA,CAAS,CAC3C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{Rect as m}from"fabric";import{forwardRef as p,useImperativeHandle as i,memo as l}from"react";import{useCreateObject as f}from"../../hooks/useCreateObject.mjs";import{useSplitProps as n}from"../../hooks/useSplitProps.mjs";const c=p(({group:r,...t},o)=>{const[s,u,a]=n(t),e=f({Constructor:m,defaultValues:a,attributes:u,group:r,listeners:s});return i(o,()=>e,[e]),null});var d=l(c);export{d as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Rect/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { Rect as BaseRect } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\n\nexport type Handle = BaseRect | undefined\n\nexport type RectProps<T = unknown> = Partial<BaseRect & AllObjectEvents> & {\n group?: BaseGroup\n defaultLeft?: number\n defaultTop?: number\n defaultWidth?: number\n defaultHeight?: number\n} & T\n\nconst Rect = forwardRef<Handle, RectProps>(({ group, ...props }, ref) => {\n const [listeners, attributes, defaultValues] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: BaseRect,\n defaultValues,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return null\n})\n\nexport default memo(Rect)\n"],"names":["Rect","forwardRef","group","props","ref","listeners","attributes","defaultValues","useSplitProps","instance","useCreateObject","BaseRect","useImperativeHandle","memo"],"mappings":"iPAiBA,MAAMA,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,GAAGC,CAAM,EAAGC,IAAQ,CACvE,KAAM,CAACC,EAAWC,EAAYC,CAAa,EAAIC,EAAcL,CAAK,EAE5DM,EAAWC,EAAgB,CAC/B,YAAaC,EACb,cAAAJ,EACA,WAAAD,EACA,MAAAJ,EACA,UAAAG,CACF,CAAC,EAED,OAAAO,EAAoBR,EAAK,IAAMK,EAAU,CAACA,CAAQ,CAAC,EAE5C,IACT,CAAC,EAED,MAAeI,EAAKb,CAAI"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{useEffect as l,useRef as g}from"react";import{shallow as D}from"zustand/shallow";import{useStore as S,useStoreApi as Z}from"../../hooks/useStore.mjs";const d=["minManualZoom","maxManualZoom","width","height","zoomable","defaultCentered","defaultSelection","defaultDraggable","selection"],n=[...d],p=e=>({setMinManualZoom:e.setMinManualZoom,setMaxManualZoom:e.setMaxManualZoom,reset:e.reset,setDefaultSelection:e.setDefaultSelection,setDefaultDraggable:e.setDefaultDraggable}),u={};function b(e){const{reset:s,setMinManualZoom:r,setMaxManualZoom:m,setDefaultSelection:f,setDefaultDraggable:i}=S(p,D),c=Z();l(()=>(f(e.defaultSelection),i(e.defaultDraggable),()=>{o.current=u,s()}),[]);const o=g(u);return l(()=>{for(const t of n){const a=e[t],M=o.current[t];a!==M&&(typeof e[t]>"u"||(t==="minManualZoom"?r(a):t==="maxManualZoom"?m(a):c.setState({[t]:a})))}o.current=e},n.map(t=>e[t])),null}export{b as StoreUpdater};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/StoreUpdater/index.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react'\nimport { shallow } from 'zustand/shallow'\nimport type { ReactFabricProps } from '../../container/ReactFabric'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { Node } from '../../types/nodes'\nimport type { ReactFabricState } from '../../types/store'\n\nconst reactFabricFieldsToTrack = [\n 'minManualZoom',\n 'maxManualZoom',\n 'width',\n 'height',\n 'zoomable',\n 'defaultCentered',\n 'defaultSelection',\n 'defaultDraggable',\n 'selection',\n] as const\n\ntype ReactFabricFieldsToTrack = (typeof reactFabricFieldsToTrack)[number]\n\ntype StoreUpdaterProps = Pick<ReactFabricProps, ReactFabricFieldsToTrack>\n\nconst fieldsToTrack = [...reactFabricFieldsToTrack, ] as const\n\nconst selector = (s: ReactFabricState) => ({\n setMinManualZoom: s.setMinManualZoom,\n setMaxManualZoom: s.setMaxManualZoom,\n reset: s.reset,\n setDefaultSelection: s.setDefaultSelection,\n setDefaultDraggable: s.setDefaultDraggable,\n})\n\nconst initPrevValues = {}\n\nexport function StoreUpdater<NodeType extends Node = Node>(props: StoreUpdaterProps) {\n const { reset, setMinManualZoom, setMaxManualZoom, setDefaultSelection,setDefaultDraggable } = useStore(selector, shallow)\n const store = useStoreApi<NodeType>()\n\n useEffect(() => {\n setDefaultSelection(props.defaultSelection)\n setDefaultDraggable(props.defaultDraggable)\n\n return () => {\n previousFields.current = initPrevValues\n reset()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const previousFields = useRef<Partial<StoreUpdaterProps>>(initPrevValues)\n\n useEffect(\n () => {\n for (const fieldName of fieldsToTrack) {\n const fieldValue = props[fieldName]\n const previousFieldValue = previousFields.current[fieldName]\n\n if (fieldValue === previousFieldValue) continue\n if (typeof props[fieldName] === 'undefined') continue\n else if (fieldName === 'minManualZoom') setMinManualZoom(fieldValue as number)\n else if (fieldName === 'maxManualZoom') setMaxManualZoom(fieldValue as number)\n else store.setState({ [fieldName]: fieldValue })\n }\n previousFields.current = props\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n fieldsToTrack.map(fieldName => props[fieldName]),\n )\n\n return null\n}\n"],"names":["reactFabricFieldsToTrack","fieldsToTrack","selector","s","initPrevValues","StoreUpdater","props","reset","setMinManualZoom","setMaxManualZoom","setDefaultSelection","setDefaultDraggable","useStore","shallow","store","useStoreApi","useEffect","previousFields","useRef","fieldName","fieldValue","previousFieldValue"],"mappings":"0KAOA,MAAMA,EAA2B,CAC/B,gBACA,gBACA,QACA,SACA,WACA,kBACA,mBACA,mBACA,WACF,EAMMC,EAAgB,CAAC,GAAGD,CAA0B,EAE9CE,EAAYC,IAAyB,CACzC,iBAAkBA,EAAE,iBACpB,iBAAkBA,EAAE,iBACpB,MAAOA,EAAE,MACT,oBAAqBA,EAAE,oBACvB,oBAAqBA,EAAE,mBACzB,GAEMC,EAAiB,CAAA,EAEP,SAAAC,EAA2CC,EAA0B,CACnF,KAAM,CAAE,MAAAC,EAAO,iBAAAC,EAAkB,iBAAAC,EAAkB,oBAAAC,EAAoB,oBAAAC,CAAoB,EAAIC,EAASV,EAAUW,CAAO,EACnHC,EAAQC,EAAAA,EAEdC,EAAU,KACRN,EAAoBJ,EAAM,gBAAgB,EAC1CK,EAAoBL,EAAM,gBAAgB,EAEnC,IAAM,CACXW,EAAe,QAAUb,EACzBG,EACF,CAAA,GAEC,CAAE,CAAA,EAEL,MAAMU,EAAiBC,EAAmCd,CAAc,EAExE,OAAAY,EACE,IAAM,CACJ,UAAWG,KAAalB,EAAe,CACrC,MAAMmB,EAAad,EAAMa,CAAS,EAC5BE,EAAqBJ,EAAe,QAAQE,CAAS,EAEvDC,IAAeC,IACf,OAAOf,EAAMa,CAAS,EAAM,MACvBA,IAAc,gBAAiBX,EAAiBY,CAAoB,EACpED,IAAc,gBAAiBV,EAAiBW,CAAoB,EACxEN,EAAM,SAAS,CAAE,CAACK,CAAS,EAAGC,CAAW,CAAC,GACjD,CACAH,EAAe,QAAUX,CAC3B,EAEAL,EAAc,IAAIkB,GAAab,EAAMa,CAAS,CAAC,CACjD,EAEO,IACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{FabricText as s}from"fabric";import{forwardRef as f,useEffect as l,useImperativeHandle as p,memo as c}from"react";import{useCreateObject as F}from"../../hooks/useCreateObject.mjs";import{useSplitProps as d}from"../../hooks/useSplitProps.mjs";import{useStoreApi as y}from"../../hooks/useStore.mjs";import b from"fontfaceobserver";const x=f(({group:r,text:o,...a},i)=>{const m=y(),[u,t]=d(a),e=F({Constructor:s,param:o,attributes:t,group:r,listeners:u});return l(()=>{const{canvas:n}=m.getState();!t.fontFamily||!e||new b(t.fontFamily).load().then(()=>{e.set({fontFamily:t.fontFamily}),n?.requestRenderAll()}).catch(()=>{console.error(`ReactFabric: \u5B57\u4F53\u52A0\u8F7D\u5931\u8D25: ${t.fontFamily}`)})},[t.fontFamily,e]),p(i,()=>e,[e]),null});var g=c(x);export{g as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Text/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { FabricText } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport FontFaceObserver from 'fontfaceobserver'\n\nexport type Handle = FabricText | undefined\n\nexport type TextProps<T = unknown> = Partial<ConstructorParameters<typeof FabricText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n} & T\n\nconst Text = forwardRef<Handle, TextProps>(({ group, text, ...props }, ref) => {\n const store = useStoreApi()\n\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: FabricText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n /**\n * 字体只有被使用了才会加载;先由 Text 使用一次, 监听加载完成,之后再 set 一次\n */\n useEffect(() => {\n const { canvas } = store.getState()\n if (!attributes.fontFamily || !instance) return\n const font = new FontFaceObserver(attributes.fontFamily)\n font\n .load()\n .then(() => {\n instance.set({\n fontFamily: attributes.fontFamily,\n })\n canvas?.requestRenderAll()\n })\n .catch(() => {\n // 加载失败\n console.error(`ReactFabric: 字体加载失败: ${attributes.fontFamily}`)\n })\n }, [attributes.fontFamily, instance])\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return null\n})\n\nexport default memo(Text)\n"],"names":["Text","forwardRef","group","text","props","ref","store","useStoreApi","listeners","attributes","useSplitProps","instance","useCreateObject","FabricText","useEffect","canvas","FontFaceObserver","useImperativeHandle","memo"],"mappings":"6VAgBA,MAAMA,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,GAAGC,CAAM,EAAGC,IAAQ,CAC7E,MAAMC,EAAQC,IAER,CAACC,EAAWC,CAAU,EAAIC,EAAcN,CAAK,EAE7CO,EAAWC,EAAgB,CAC/B,YAAaC,EACb,MAAOV,EACP,WAAAM,EACA,MAAAP,EACA,UAAAM,CACF,CAAC,EAKD,OAAAM,EAAU,IAAM,CACd,KAAM,CAAE,OAAAC,CAAO,EAAIT,EAAM,SAAS,EAC9B,CAACG,EAAW,YAAc,CAACE,GAClB,IAAIK,EAAiBP,EAAW,UAAU,EAEpD,OACA,KAAK,IAAM,CACVE,EAAS,IAAI,CACX,WAAYF,EAAW,UACzB,CAAC,EACDM,GAAQ,iBAAA,CACV,CAAC,EACA,MAAM,IAAM,CAEX,QAAQ,MAAM,sDAAwBN,EAAW,UAAU,EAAE,CAC/D,CAAC,CACL,EAAG,CAACA,EAAW,WAAYE,CAAQ,CAAC,EAEpCM,EAAoBZ,EAAK,IAAMM,EAAU,CAACA,CAAQ,CAAC,EAE5C,IACT,CAAC,EAED,MAAeO,EAAKlB,CAAI"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as e,Fragment as d}from"react/jsx-runtime";import{useContext as a}from"react";import{ReactFabricProvider as l}from"../../components/ReactFabricProvider.mjs";import m from"../../contexts/StoreContext.mjs";function h({children:i,nodes:t,defaultNodes:r,width:o,height:n}){return a(m)?e(d,{children:i}):e(l,{initialNodes:t,defaultNodes:r,initialWidth:o,initialHeight:n,children:i})}export{h as Wrapper};
|
|
2
|
+
//# sourceMappingURL=Wrapper.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wrapper.mjs","sources":["../../../../src/container/ReactFabric/Wrapper.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { useContext } from 'react'\nimport { ReactFabricProvider } from '../../components/ReactFabricProvider'\nimport StoreContext from '../../contexts/StoreContext'\nimport type { Node } from '../../types/nodes'\n\nexport function Wrapper({\n children,\n nodes,\n defaultNodes,\n width,\n height,\n}: {\n children: ReactNode\n nodes?: Node[]\n defaultNodes?: Node[]\n width?: number\n height?: number\n}) {\n const isWrapped = useContext(StoreContext)\n\n if (isWrapped) {\n return <>{children}</>\n }\n\n return (\n <ReactFabricProvider initialNodes={nodes} defaultNodes={defaultNodes} initialWidth={width} initialHeight={height}>\n {children}\n </ReactFabricProvider>\n )\n}\n"],"names":["Wrapper","children","nodes","defaultNodes","width","height","useContext","StoreContext","jsx","Fragment","ReactFabricProvider"],"mappings":"oOAMgB,SAAAA,EAAQ,CACtB,SAAAC,EACA,MAAAC,EACA,aAAAC,EACA,MAAAC,EACA,OAAAC,CACF,EAMG,CAGD,OAFkBC,EAAWC,CAAY,EAGhCC,EAAAC,EAAA,CAAG,SAAAR,CAAS,CAAA,EAInBO,EAACE,EAAA,CAAoB,aAAcR,EAAO,aAAcC,EAAc,aAAcC,EAAO,cAAeC,EACvG,SAAAJ,CAAAA,CACH,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as x}from"react/jsx-runtime";import{forwardRef as v,memo as D}from"react";import{Wrapper as Z}from"./Wrapper.mjs";import y from"../../components/Canvas/index.mjs";import z from"../../components/Loading/index.mjs";import{StoreUpdater as N}from"../../components/StoreUpdater/index.mjs";const S={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},U=v(({minManualZoom:a,maxManualZoom:t,className:l,children:r,width:i,height:n,selection:m,style:s,onMouseWheel:d,onMouseDown:u,onMouseMove:f,onMouseUp:c,zoomable:h,defaultSelection:p,defaultCentered:M,defaultDraggable:g,...w},b)=>e("div",{style:{...s,...S},ref:b,className:`react-fabric ${l||""}`,children:x(Z,{width:i,height:n,children:[e(N,{minManualZoom:a,maxManualZoom:t,zoomable:h,defaultCentered:M,selection:m,defaultSelection:p,defaultDraggable:g}),e(y,{onMouseDown:u,onMouseMove:f,onMouseUp:c,onMouseWheel:d,...w,children:r}),e(z,{})]})})),o=D(U);o.displayName="ReactFabric";export{o as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\n\n// 自定义基础事件类型\ntype FabricEvent = {\n e: Event\n pointer: { x: number; y: number }\n target?: unknown\n subTargets?: unknown[]\n button?: number\n isClick?: boolean\n transform?: unknown\n}\n\n// 重新定义 CanvasProps,不再从 components/Canvas 导入\ntype BaseCanvasProps = {\n width?: number\n height?: number\n selection?: boolean\n children?: React.ReactNode\n // 添加其他必要的 Canvas 属性\n}\n\nimport { Wrapper } from './Wrapper'\n\nimport Canvas from '../../components/Canvas'\nimport Loading from '../../components/Loading'\nimport { StoreUpdater } from '../../components/StoreUpdater'\n\nconst wrapperStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 0,\n}\n\nexport type ReactFabricProps = BaseCanvasProps & {\n style?: CSSProperties\n className?: string\n zoomable?: boolean\n minManualZoom?: number\n maxManualZoom?: number\n /** 背景图是否默认居中显示\n * @default false\n */\n defaultCentered?: boolean\n /** 是否启用选择功能\n * @default true\n * */\n defaultSelection?: boolean\n /**\n * 是否默认可拖拽\n */\n defaultDraggable?: boolean\n onMouseDown?: (e: FabricEvent) => void\n onMouseMove?: (e: FabricEvent) => void\n onMouseUp?: (e: FabricEvent) => void\n onMouseWheel?: (e: FabricEvent) => void\n}\n\nconst ForwardReactFabric = forwardRef<HTMLDivElement, ReactFabricProps>(\n (\n {\n minManualZoom,\n maxManualZoom,\n className,\n children,\n width,\n height,\n selection,\n style,\n onMouseWheel,\n onMouseDown,\n onMouseMove,\n onMouseUp,\n zoomable,\n defaultSelection,\n defaultCentered,\n defaultDraggable,\n ...rest\n },\n ref,\n ) => {\n return (\n <div style={{ ...style, ...wrapperStyle }} ref={ref} className={`react-fabric ${className || ''}`}>\n <Wrapper width={width} height={height}>\n <StoreUpdater\n minManualZoom={minManualZoom}\n maxManualZoom={maxManualZoom}\n zoomable={zoomable}\n defaultCentered={defaultCentered}\n selection={selection}\n defaultSelection={defaultSelection}\n defaultDraggable={defaultDraggable}\n />\n\n <Canvas\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onMouseWheel={onMouseWheel}\n {...rest}\n >\n {children}\n </Canvas>\n <Loading />\n </Wrapper>\n </div>\n )\n },\n)\n\ntype ReactFabricComponent = React.MemoExoticComponent<typeof ForwardReactFabric>\n\nconst ReactFabric: ReactFabricComponent = memo(ForwardReactFabric)\nReactFabric.displayName = 'ReactFabric'\n\nexport default ReactFabric\n"],"names":["wrapperStyle","ForwardReactFabric","forwardRef","minManualZoom","maxManualZoom","className","children","width","height","selection","style","onMouseWheel","onMouseDown","onMouseMove","onMouseUp","zoomable","defaultSelection","defaultCentered","defaultDraggable","rest","ref","jsx","jsxs","Wrapper","StoreUpdater","Canvas","Loading","ReactFabric","memo"],"mappings":"8TA6BMA,MAAAA,EAA8B,CAClC,MAAO,OACP,OAAQ,OACR,SAAU,SACV,SAAU,WACV,OAAQ,CACV,EA0BMC,EAAqBC,EACzB,CACE,CACE,cAAAC,EACA,cAAAC,EACA,UAAAC,EACA,SAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,MAAAC,EACA,aAAAC,EACA,YAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAAC,EACA,iBAAAC,EACA,gBAAAC,EACA,iBAAAC,EACA,GAAGC,CACL,EACAC,IAGEC,EAAC,MAAI,CAAA,MAAO,CAAE,GAAGX,EAAO,GAAGV,CAAa,EAAG,IAAKoB,EAAK,UAAW,gBAAgBf,GAAa,EAAE,GAC7F,SAAAiB,EAACC,EAAA,CAAQ,MAAOhB,EAAO,OAAQC,EAC7B,SAAAa,CAAAA,EAACG,EAAA,CACC,cAAerB,EACf,cAAeC,EACf,SAAUW,EACV,gBAAiBE,EACjB,UAAWR,EACX,iBAAkBO,EAClB,iBAAkBE,CAAAA,CACpB,EAEAG,EAACI,EAAA,CACC,YAAab,EACb,YAAaC,EACb,UAAWC,EACX,aAAcH,EACb,GAAGQ,EAEH,SAAAb,EACH,EACAe,EAACK,EAAA,CAAQ,CAAA,GACX,CACF,CAAA,CAGN,EAIMC,EAAoCC,EAAK3B,CAAkB,EACjE0B,EAAY,YAAc"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StoreContext.mjs","sources":["../../../src/contexts/StoreContext.ts"],"sourcesContent":["import { createContext } from 'react'\n\nimport type { createStore } from '../store'\n\nconst StoreContext = createContext<ReturnType<typeof createStore> | null>(null)\n\nexport const Provider = StoreContext.Provider\nexport default StoreContext\n"],"names":["StoreContext","createContext","Provider"],"mappings":"mDAIA,MAAMA,EAAeC,EAAqD,IAAI,EAEjEC,EAAWF,EAAa"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{useRef as v,useMemo as g,useEffect as h}from"react";import{bindEvents as j}from"../utils/events.mjs";import{transformDefaultProps as w}from"../utils/props.mjs";import{useDidUpdate as y}from"./useDidUpdate.mjs";import{useStoreApi as C,useStore as E}from"./useStore.mjs";function F({Constructor:s,attributes:o,defaultValues:c={},param:u,group:i,listeners:l={}}){const a=C(),f=E(t=>t.canvas),d=v(null),e=g(()=>{const t=Object.keys(c).length>0;d.current=t?"uncontrolled":"controlled";const n={...o,...w(c)};return u!==void 0?new s(u,n):new s(n)},[s,u]),r=g(()=>i??f,[i,f]);return h(()=>{if(!(!e||!r))return r.add(e),()=>{try{e&&(e.off(),r.contains(e)&&r.remove(e),typeof e.dispose=="function"&&e.dispose())}catch(t){console.warn("\u6E05\u7406\u5BF9\u8C61\u65F6\u53D1\u751F\u9519\u8BEF:",t)}}},[e,r]),h(()=>{if(e)return j(e,l)},[e,l]),y(()=>{if(!e)return;const{canvas:t}=a.getState();if(d.current==="uncontrolled"){const n=Object.entries(o).reduce((p,[m,b])=>(m.match(/^(left|top|width|height|scaleX|scaleY|angle|points|path|originX|originY)$/)||(p[m]=b),p),{});Object.keys(n).length>0&&(e.set(n),t?.requestRenderAll())}else e.set(o),e.setCoords(),t?.requestRenderAll()},[e,o,a]),e}export{F as useCreateObject};
|
|
2
|
+
//# sourceMappingURL=useCreateObject.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCreateObject.mjs","sources":["../../../src/hooks/useCreateObject.ts"],"sourcesContent":["import type { FabricObject, Group } from 'fabric'\nimport { useEffect, useMemo, useRef } from 'react'\nimport type { AllObjectEvents } from '../types/object'\nimport { bindEvents } from '../utils/events'\nimport { transformDefaultProps } from '../utils/props'\nimport { useDidUpdate } from './useDidUpdate'\nimport { useStore, useStoreApi } from './useStore'\n\ntype SingleParamConstructor<T> = new (attributes: any) => T\ntype DualParamConstructor<T, P> = new (param: P, attributes: any) => T\n\ntype CreateObjectProps<T extends FabricObject, P = any> = {\n Constructor: SingleParamConstructor<T> | DualParamConstructor<T, P>\n attributes: any\n defaultValues?: any\n param?: P\n group?: Group\n listeners?: Partial<AllObjectEvents>\n}\n\nexport function useCreateObject<T extends FabricObject, P = any>({\n Constructor,\n attributes,\n defaultValues = {},\n param,\n group,\n listeners = {},\n}: CreateObjectProps<T, P>) {\n const store = useStoreApi()\n const canvas = useStore( state => state.canvas)\n\n\n // 使用 ref 记录控制模式\n const modeRef = useRef<'controlled' | 'uncontrolled' | null>(null)\n\n // 在创建实例时确定控制模式\n const instance = useMemo(() => {\n const hasUncontrolledProps = Object.keys(defaultValues).length > 0\n modeRef.current = hasUncontrolledProps ? 'uncontrolled' : 'controlled'\n\n const mergedAttributes = {\n ...attributes,\n ...transformDefaultProps(defaultValues),\n }\n\n const newInstance =\n param !== undefined\n ? new (Constructor as DualParamConstructor<T, P>)(param, mergedAttributes)\n : new (Constructor as SingleParamConstructor<T>)(mergedAttributes)\n return newInstance\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [Constructor, param])\n\n // 计算父容器(group 或 canvas)\n const parent = useMemo(() => group ?? canvas, [group, canvas])\n\n // 处理实例的添加和移除\n useEffect(() => {\n if (!instance || !parent) return\n // 添加到父容器\n parent.add(instance)\n\n return () => {\n try {\n if (instance) {\n // 移除所有事件监听\n instance.off()\n\n // 从父容器中移除\n if (parent.contains(instance)) {\n parent.remove(instance)\n }\n\n // 如果存在 dispose 方法则调用\n if (typeof instance.dispose === 'function') {\n instance.dispose()\n }\n }\n } catch (error) {\n console.warn('清理对象时发生错误:', error)\n }\n }\n }, [instance, parent])\n\n // 处理事件绑定\n useEffect(() => {\n if (!instance) return\n return bindEvents(instance, listeners)\n }, [instance, listeners])\n\n // 处理属性更新\n useDidUpdate(() => {\n if (!instance) return\n const { canvas } = store.getState()\n\n // 在非受控模式下,跳过位置相关属性的更新\n if (modeRef.current === 'uncontrolled') {\n const styleUpdates = Object.entries(attributes).reduce(\n (acc, [key, value]) => {\n if (!key.match(/^(left|top|width|height|scaleX|scaleY|angle|points|path|originX|originY)$/)) {\n acc[key] = value\n }\n return acc\n },\n {} as Record<string, any>,\n )\n\n if (Object.keys(styleUpdates).length > 0) {\n instance.set(styleUpdates)\n canvas?.requestRenderAll()\n }\n } else {\n // 受控模式:正常更新所有属性\n instance.set(attributes)\n instance.setCoords()\n canvas?.requestRenderAll()\n }\n }, [instance, attributes, store])\n\n return instance\n}\n"],"names":["useCreateObject","Constructor","attributes","defaultValues","param","group","listeners","store","useStoreApi","canvas","useStore","state","modeRef","useRef","instance","useMemo","hasUncontrolledProps","mergedAttributes","transformDefaultProps","parent","useEffect","error","bindEvents","useDidUpdate","styleUpdates","acc","key","value"],"mappings":"iSAoBO,SAASA,EAAiD,CAC/D,YAAAC,EACA,WAAAC,EACA,cAAAC,EAAgB,GAChB,MAAAC,EACA,MAAAC,EACA,UAAAC,EAAY,CAAA,CACd,EAA4B,CAC1B,MAAMC,EAAQC,EACRC,EAAAA,EAASC,EAAUC,GAASA,EAAM,MAAM,EAIxCC,EAAUC,EAA6C,IAAI,EAG3DC,EAAWC,EAAQ,IAAM,CAC7B,MAAMC,EAAuB,OAAO,KAAKb,CAAa,EAAE,OAAS,EACjES,EAAQ,QAAUI,EAAuB,eAAiB,aAE1D,MAAMC,EAAmB,CACvB,GAAGf,EACH,GAAGgB,EAAsBf,CAAa,CACxC,EAMA,OAHEC,IAAU,OACN,IAAKH,EAA2CG,EAAOa,CAAgB,EACvE,IAAKhB,EAA0CgB,CAAgB,CAGvE,EAAG,CAAChB,EAAaG,CAAK,CAAC,EAGjBe,EAASJ,EAAQ,IAAMV,GAASI,EAAQ,CAACJ,EAAOI,CAAM,CAAC,EAG7D,OAAAW,EAAU,IAAM,CACd,GAAI,EAAA,CAACN,GAAY,CAACK,GAElB,OAAAA,EAAO,IAAIL,CAAQ,EAEZ,IAAM,CACX,GAAI,CACEA,IAEFA,EAAS,IAGLK,EAAAA,EAAO,SAASL,CAAQ,GAC1BK,EAAO,OAAOL,CAAQ,EAIpB,OAAOA,EAAS,SAAY,YAC9BA,EAAS,QAAQ,EAGvB,OAASO,EAAO,CACd,QAAQ,KAAK,0DAAcA,CAAK,CAClC,CACF,CACF,EAAG,CAACP,EAAUK,CAAM,CAAC,EAGrBC,EAAU,IAAM,CACd,GAAKN,EACL,OAAOQ,EAAWR,EAAUR,CAAS,CACvC,EAAG,CAACQ,EAAUR,CAAS,CAAC,EAGxBiB,EAAa,IAAM,CACjB,GAAI,CAACT,EAAU,OACf,KAAM,CAAE,OAAAL,CAAO,EAAIF,EAAM,SAGzB,EAAA,GAAIK,EAAQ,UAAY,eAAgB,CACtC,MAAMY,EAAe,OAAO,QAAQtB,CAAU,EAAE,OAC9C,CAACuB,EAAK,CAACC,EAAKC,CAAK,KACVD,EAAI,MAAM,2EAA2E,IACxFD,EAAIC,CAAG,EAAIC,GAENF,GAET,EACF,EAEI,OAAO,KAAKD,CAAY,EAAE,OAAS,IACrCV,EAAS,IAAIU,CAAY,EACzBf,GAAQ,mBAEZ,MAEEK,EAAS,IAAIZ,CAAU,EACvBY,EAAS,UAAA,EACTL,GAAQ,iBAEZ,CAAA,EAAG,CAACK,EAAUZ,EAAYK,CAAK,CAAC,EAEzBO,CACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDidUpdate.mjs","sources":["../../../src/hooks/useDidUpdate.ts"],"sourcesContent":["import type { DependencyList, EffectCallback } from 'react'\nimport { useEffect, useRef } from 'react'\n\n/**\n * 只在依赖更新时执行的 effect hook\n * @param effect 要执行的副作用函数\n * @param deps 依赖数组\n * https://mantine.dev/hooks/use-did-update/\n */\nexport function useDidUpdate(effect: EffectCallback, deps?: DependencyList): void {\n const didMount = useRef(false)\n\n useEffect(() => {\n if (didMount.current) {\n return effect()\n }\n\n didMount.current = true\n return undefined\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps)\n}\n"],"names":["useDidUpdate","effect","deps","didMount","useRef","useEffect"],"mappings":"2DASO,SAASA,EAAaC,EAAwBC,EAA6B,CAChF,MAAMC,EAAWC,EAAO,EAAK,EAE7BC,EAAU,IAAM,CACd,GAAIF,EAAS,QACX,OAAOF,EAAO,EAGhBE,EAAS,QAAU,EAIrB,EAAGD,CAAI,CACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{shallow as p}from"zustand/shallow";import{useRef as a,useEffect as d}from"react";import{useStoreApi as v,useStore as b}from"./useStore.mjs";const h=r=>({canvas:r.canvas,draggable:r.draggable}),w=r=>{const e=r.get("selectable");return r.set("selectable",!1),()=>{r.set("selectable",e)}},T=r=>{if(!r)return()=>{};const e=r.getObjects().map(n=>w(n));return()=>{e.forEach(n=>n())}},X=()=>{const r=v(),{canvas:e,draggable:n}=b(h,p),s=a(0),u=a(0),l=a(!1);return d(()=>{if(!n)return;const g=T(e),i=({e:t})=>{const c=t.changedTouches?.[0];l.current=!0,s.current=t.clientX??c?.clientX,u.current=t.clientY??c?.clientY},f=({e:t})=>{if(l.current&&e){var c=e.viewportTransform;const o=t.changedTouches?.[0];c[4]+=(t.clientX??o?.clientX)-s.current,c[5]+=(t.clientY??o?.clientY)-u.current,e.requestRenderAll(),s.current=t.clientX??o?.clientX,u.current=t.clientY??o?.clientY}},m=t=>{e&&(e.setViewportTransform(e.viewportTransform),l.current=!1)};return e?.on("mouse:down",i),e?.on("mouse:move",f),e?.on("mouse:up",m),()=>{g(),e?.off("mouse:down",i),e?.off("mouse:move",f),e?.off("mouse:up",m)}},[e,n,r]),null};export{X as default};
|
|
2
|
+
//# sourceMappingURL=useDraggable.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDraggable.mjs","sources":["../../../src/hooks/useDraggable.ts"],"sourcesContent":["import type { Canvas, FabricObject, TPointerEvent, TPointerEventInfo } from 'fabric'\nimport { shallow } from 'zustand/shallow'\nimport { useEffect, useRef } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n canvas: s.canvas,\n draggable: s.draggable,\n})\n\nconst stageObject = (object: FabricObject) => {\n const raw = object.get('selectable')\n object.set('selectable', false)\n\n return () => {\n object.set('selectable', raw)\n }\n}\n\nconst stage = (canvas: Canvas | null) => {\n if (!canvas) return () => {}\n const objects = canvas.getObjects()\n\n const unStagedList = objects.map(object => {\n return stageObject(object)\n })\n\n return () => {\n unStagedList.forEach(fn => fn())\n }\n}\n\nconst useDraggable = () => {\n const store = useStoreApi()\n const { canvas, draggable } = useStore(selector, shallow)\n const lastPosXRef = useRef(0)\n const lastPosYRef = useRef(0)\n const isDraggingRef = useRef(false)\n\n useEffect(() => {\n if (!draggable) return\n const unStaged = stage(canvas)\n\n const onMouseDown = ({ e }: TPointerEventInfo<MouseEvent>) => {\n // @ts-expect-error 触摸屏拿不到clintX\n const touch = e.changedTouches?.[0]\n isDraggingRef.current = true\n lastPosXRef.current = e.clientX ?? touch?.clientX\n lastPosYRef.current = e.clientY ?? touch?.clientY\n }\n\n const onMouseMove = ({ e }: TPointerEventInfo<MouseEvent>) => {\n if (isDraggingRef.current && canvas) {\n var vpt = canvas.viewportTransform\n // @ts-expect-error 触摸屏拿不到clintX\n const touch = e.changedTouches?.[0]\n vpt[4] += (e.clientX ?? touch?.clientX) - lastPosXRef.current!\n vpt[5] += (e.clientY ?? touch?.clientY) - lastPosYRef.current!\n canvas.requestRenderAll()\n lastPosXRef.current = e.clientX ?? touch?.clientX\n lastPosYRef.current = e.clientY ?? touch?.clientY\n }\n }\n\n const onMouseUp = (_: TPointerEventInfo<TPointerEvent>) => {\n if (canvas) {\n canvas.setViewportTransform(canvas.viewportTransform)\n isDraggingRef.current = false\n }\n }\n\n canvas?.on('mouse:down', onMouseDown)\n canvas?.on('mouse:move', onMouseMove)\n canvas?.on('mouse:up', onMouseUp)\n\n return () => {\n unStaged()\n canvas?.off('mouse:down', onMouseDown)\n canvas?.off('mouse:move', onMouseMove)\n canvas?.off('mouse:up', onMouseUp)\n }\n }, [canvas, draggable, store])\n\n return null\n}\n\nexport default useDraggable\n"],"names":["selector","s","stageObject","object","raw","stage","canvas","unStagedList","fn","useDraggable","store","useStoreApi","draggable","useStore","shallow","lastPosXRef","useRef","lastPosYRef","isDraggingRef","useEffect","unStaged","onMouseDown","e","touch","onMouseMove","vpt","onMouseUp","_"],"mappings":"gKAMMA,MAAAA,EAAYC,IAAyB,CACzC,OAAQA,EAAE,OACV,UAAWA,EAAE,SACf,GAEMC,EAAeC,GAAyB,CAC5C,MAAMC,EAAMD,EAAO,IAAI,YAAY,EACnC,OAAAA,EAAO,IAAI,aAAc,EAAK,EAEvB,IAAM,CACXA,EAAO,IAAI,aAAcC,CAAG,CAC9B,CACF,EAEMC,EAASC,GAA0B,CACvC,GAAI,CAACA,EAAQ,MAAO,IAAM,CAAA,EAG1B,MAAMC,EAFUD,EAAO,aAEM,IAAIH,GACxBD,EAAYC,CAAM,CAC1B,EAED,MAAO,IAAM,CACXI,EAAa,QAAQC,GAAMA,EAAAA,CAAI,CACjC,CACF,EAEMC,EAAe,IAAM,CACzB,MAAMC,EAAQC,EAAY,EACpB,CAAE,OAAAL,EAAQ,UAAAM,CAAU,EAAIC,EAASb,EAAUc,CAAO,EAClDC,EAAcC,EAAO,CAAC,EACtBC,EAAcD,EAAO,CAAC,EACtBE,EAAgBF,EAAO,EAAK,EAElC,OAAAG,EAAU,IAAM,CACd,GAAI,CAACP,EAAW,OAChB,MAAMQ,EAAWf,EAAMC,CAAM,EAEvBe,EAAc,CAAC,CAAE,EAAAC,CAAE,IAAqC,CAE5D,MAAMC,EAAQD,EAAE,iBAAiB,CAAC,EAClCJ,EAAc,QAAU,GACxBH,EAAY,QAAUO,EAAE,SAAWC,GAAO,QAC1CN,EAAY,QAAUK,EAAE,SAAWC,GAAO,OAC5C,EAEMC,EAAc,CAAC,CAAE,EAAAF,CAAE,IAAqC,CAC5D,GAAIJ,EAAc,SAAWZ,EAAQ,CACnC,IAAImB,EAAMnB,EAAO,kBAEjB,MAAMiB,EAAQD,EAAE,iBAAiB,CAAC,EAClCG,EAAI,CAAC,IAAMH,EAAE,SAAWC,GAAO,SAAWR,EAAY,QACtDU,EAAI,CAAC,IAAMH,EAAE,SAAWC,GAAO,SAAWN,EAAY,QACtDX,EAAO,iBAAA,EACPS,EAAY,QAAUO,EAAE,SAAWC,GAAO,QAC1CN,EAAY,QAAUK,EAAE,SAAWC,GAAO,OAC5C,CACF,EAEMG,EAAaC,GAAwC,CACrDrB,IACFA,EAAO,qBAAqBA,EAAO,iBAAiB,EACpDY,EAAc,QAAU,GAE5B,EAEA,OAAAZ,GAAQ,GAAG,aAAce,CAAW,EACpCf,GAAQ,GAAG,aAAckB,CAAW,EACpClB,GAAQ,GAAG,WAAYoB,CAAS,EAEzB,IAAM,CACXN,EAAAA,EACAd,GAAQ,IAAI,aAAce,CAAW,EACrCf,GAAQ,IAAI,aAAckB,CAAW,EACrClB,GAAQ,IAAI,WAAYoB,CAAS,CACnC,CACF,EAAG,CAACpB,EAAQM,EAAWF,CAAK,CAAC,EAEtB,IACT"}
|
|
@@ -0,0 +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=t=>({draggable:t.draggable,selection:t.selection,isDragging:t.isDragging,width:t.width,height:t.height,canvas:t.canvas,setDraggable:t.setDraggable,setIsDragging:t.setIsDragging,lastPosX:t.lastPosX,lastPosY:t.lastPosY,setSelection:t.setSelection,zoomable:t.zoomable,setZoomable:t.setZoomable,scale:t.scale,zoom:t.zoom,defaultCentered:t.defaultCentered,manualZoom:t.manualZoom,maxManualZoom:t.maxManualZoom,minManualZoom:t.minManualZoom,loading:t.loading});function b(){const t=Z(),i=S(f,d),l=r(()=>({getCanvas:()=>t.getState().canvas,getNodes:()=>t.getState().nodes.map(e=>({...e})),getState:()=>t.getState,zoomIn:()=>{let{manualZoom:e,canvas:o,fitZoom:s}=t.getState();e+=.2;const n=t.getState().maxManualZoom,a=t.getState().minManualZoom;e>n&&(e=n),e<a&&(e=a);const m=e*s;if(o?.backgroundImage&&o){const g=o.getCenterPoint();o.zoomToPoint(g,m)}t.setState({manualZoom:e,zoom:m})},zoomOut:()=>{let{manualZoom:e,canvas:o,fitZoom:s}=t.getState();e-=.2;const n=t.getState().maxManualZoom,a=t.getState().minManualZoom;e>n&&(e=n),e<a&&(e=a);const m=e*s;if(o?.backgroundImage&&o){const g=o.getCenterPoint();o.zoomToPoint(g,m)}t.setState({manualZoom:e,zoom:m})},getZoom:()=>t.getState().zoom,resetViewport:()=>{let{canvas:e,fitZoom:o=1,defaultCentered:s}=t.getState();const n=1,a=n*o;if(e){if(s&&e.backgroundImage){const m=e.backgroundImage.width||0,g=e.backgroundImage.height||0,u=(e.width-m*a)/2,c=(e.height-g*a)/2;e.setViewportTransform([a,0,0,a,u,c])}else e.setViewportTransform([a,0,0,a,0,0]);e.requestRenderAll()}t.setState({manualZoom:n,zoom:a})}}),[t]);return r(()=>({...l,...i}),[l,i])}export{b as useReactFabric};
|
|
2
|
+
//# sourceMappingURL=useReactFabric.mjs.map
|
|
@@ -0,0 +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: () => {\n let { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const manualZoom = 1\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,SAAS,EACrDQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAA,EAAW,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAA,EACtBA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,WAAW,KAKhC,cAAe,IAAM,CACnB,GAAI,CAAE,OAAAS,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAA,EAErD,MAAMQ,EAAa,EACbK,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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{throttle as r}from"lodash-es";import{useCallback as c,useEffect as d}from"react";import{useStore as a}from"./useStore.mjs";const m=()=>{const{domNode:t,canvas:n,setDimensions:i}=a(e=>({domNode:e.domNode,canvas:e.canvas,setDimensions:e.setDimensions})),o=c(()=>{if(!t||!n)return;const{width:e,height:s}=t.getBoundingClientRect();i({width:e,height:s})},[t,n,i]);d(()=>{if(!t||!n)return;o();const e=r(o,200,{leading:!0,trailing:!0});window.addEventListener("resize",e);const s=new ResizeObserver(e);return s.observe(t),()=>{window.removeEventListener("resize",e),s.disconnect(),e.cancel()}},[o,t,n])};export{m as default};
|
|
2
|
+
//# sourceMappingURL=useResizeHandler.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResizeHandler.mjs","sources":["../../../src/hooks/useResizeHandler.ts"],"sourcesContent":["import { throttle } from 'lodash-es'\nimport { useCallback, useEffect } from 'react'\nimport { useStore } from './useStore'\n\nconst useResizeHandler = () => {\n const { domNode, canvas, setDimensions } = useStore(state => ({\n domNode: state.domNode,\n canvas: state.canvas,\n setDimensions: state.setDimensions,\n }))\n\n const updateDimensions = useCallback(() => {\n if (!domNode || !canvas) return\n\n // 获取父容器的尺寸\n const { width, height } = domNode.getBoundingClientRect()\n\n // 使用 store 中的 setDimensions 方法\n setDimensions({ width, height })\n\n // canvas.requestRenderAll()\n }, [domNode, canvas, setDimensions])\n\n useEffect(() => {\n if (!domNode || !canvas) return\n\n // 初始化时立即计算一次\n updateDimensions()\n const throttledUpdate = throttle(updateDimensions, 200, {\n leading: true,\n trailing: true,\n })\n\n window.addEventListener('resize', throttledUpdate)\n const resizeObserver = new ResizeObserver(throttledUpdate)\n resizeObserver.observe(domNode)\n\n return () => {\n window.removeEventListener('resize', throttledUpdate)\n resizeObserver.disconnect()\n throttledUpdate.cancel()\n }\n }, [updateDimensions, domNode, canvas])\n}\n\nexport default useResizeHandler\n"],"names":["useResizeHandler","domNode","canvas","setDimensions","useStore","state","updateDimensions","useCallback","width","height","useEffect","throttledUpdate","throttle","resizeObserver"],"mappings":"+IAIMA,MAAAA,EAAmB,IAAM,CAC7B,KAAM,CAAE,QAAAC,EAAS,OAAAC,EAAQ,cAAAC,CAAc,EAAIC,EAASC,IAAU,CAC5D,QAASA,EAAM,QACf,OAAQA,EAAM,OACd,cAAeA,EAAM,aACvB,EAAE,EAEIC,EAAmBC,EAAY,IAAM,CACzC,GAAI,CAACN,GAAW,CAACC,EAAQ,OAGzB,KAAM,CAAE,MAAAM,EAAO,OAAAC,CAAO,EAAIR,EAAQ,wBAGlCE,EAAc,CAAE,MAAAK,EAAO,OAAAC,CAAO,CAAC,CAGjC,EAAG,CAACR,EAASC,EAAQC,CAAa,CAAC,EAEnCO,EAAU,IAAM,CACd,GAAI,CAACT,GAAW,CAACC,EAAQ,OAGzBI,EACA,EAAA,MAAMK,EAAkBC,EAASN,EAAkB,IAAK,CACtD,QAAS,GACT,SAAU,EACZ,CAAC,EAED,OAAO,iBAAiB,SAAUK,CAAe,EACjD,MAAME,EAAiB,IAAI,eAAeF,CAAe,EACzD,OAAAE,EAAe,QAAQZ,CAAO,EAEvB,IAAM,CACX,OAAO,oBAAoB,SAAUU,CAAe,EACpDE,EAAe,WAAW,EAC1BF,EAAgB,QAClB,CACF,EAAG,CAACL,EAAkBL,EAASC,CAAM,CAAC,CACxC"}
|