@cs-open/react-fabric 0.0.7 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/BackgroundImage/index.cjs +1 -1
- package/dist/cjs/components/BackgroundImage/index.cjs.map +1 -1
- package/dist/cjs/components/Canvas/index.cjs +1 -1
- package/dist/cjs/components/Canvas/index.cjs.map +1 -1
- package/dist/cjs/components/Control2/index.cjs +2 -0
- package/dist/cjs/components/Control2/index.cjs.map +1 -0
- package/dist/cjs/components/Ellipse/index.cjs +1 -1
- package/dist/cjs/components/Ellipse/index.cjs.map +1 -1
- package/dist/cjs/components/Group/index.cjs.map +1 -1
- package/dist/cjs/components/IText/index.cjs +1 -1
- package/dist/cjs/components/IText/index.cjs.map +1 -1
- package/dist/cjs/components/Image/index.cjs +1 -1
- package/dist/cjs/components/Image/index.cjs.map +1 -1
- package/dist/cjs/components/Line/index.cjs +1 -1
- package/dist/cjs/components/Line/index.cjs.map +1 -1
- package/dist/cjs/components/Loading/index.cjs +10 -1
- package/dist/cjs/components/Loading/index.cjs.map +1 -1
- package/dist/cjs/components/Path/index.cjs +1 -1
- package/dist/cjs/components/Path/index.cjs.map +1 -1
- package/dist/cjs/components/Polyline/index.cjs +1 -1
- package/dist/cjs/components/Polyline/index.cjs.map +1 -1
- package/dist/cjs/components/Rect/index.cjs +1 -1
- package/dist/cjs/components/Rect/index.cjs.map +1 -1
- package/dist/cjs/components/StoreUpdater/index.cjs +1 -1
- package/dist/cjs/components/StoreUpdater/index.cjs.map +1 -1
- package/dist/cjs/components/Text/index.cjs +1 -1
- package/dist/cjs/components/Text/index.cjs.map +1 -1
- package/dist/cjs/components/Textbox/index.cjs +1 -1
- package/dist/cjs/components/Textbox/index.cjs.map +1 -1
- package/dist/cjs/components/WavyLine/index.cjs +1 -1
- package/dist/cjs/components/WavyLine/index.cjs.map +1 -1
- package/dist/cjs/container/ReactFabric/index.cjs +1 -1
- package/dist/cjs/container/ReactFabric/index.cjs.map +1 -1
- package/dist/cjs/hooks/useInstancePosition.cjs +2 -0
- package/dist/cjs/hooks/useInstancePosition.cjs.map +1 -0
- package/dist/cjs/hooks/useReactFabric.cjs +1 -1
- package/dist/cjs/hooks/useReactFabric.cjs.map +1 -1
- package/dist/cjs/hooks/useStore.cjs +1 -1
- package/dist/cjs/hooks/useStore.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/plugins/index.cjs +1 -1
- package/dist/cjs/store/index.cjs +1 -1
- package/dist/cjs/store/index.cjs.map +1 -1
- package/dist/cjs/store/initialState.cjs +1 -1
- package/dist/cjs/store/initialState.cjs.map +1 -1
- package/dist/cjs/utils/childrenWithPosition.cjs +2 -0
- package/dist/cjs/utils/childrenWithPosition.cjs.map +1 -0
- package/dist/esm/components/BackgroundImage/index.mjs +1 -1
- package/dist/esm/components/BackgroundImage/index.mjs.map +1 -1
- package/dist/esm/components/Canvas/index.mjs +1 -1
- package/dist/esm/components/Canvas/index.mjs.map +1 -1
- package/dist/esm/components/Control2/index.mjs +2 -0
- package/dist/esm/components/Control2/index.mjs.map +1 -0
- package/dist/esm/components/Ellipse/index.mjs +1 -1
- package/dist/esm/components/Ellipse/index.mjs.map +1 -1
- package/dist/esm/components/Group/index.mjs.map +1 -1
- package/dist/esm/components/IText/index.mjs +1 -1
- package/dist/esm/components/IText/index.mjs.map +1 -1
- package/dist/esm/components/Image/index.mjs +2 -0
- package/dist/esm/components/Image/index.mjs.map +1 -0
- package/dist/esm/components/Line/index.mjs +1 -1
- package/dist/esm/components/Line/index.mjs.map +1 -1
- package/dist/esm/components/Loading/index.mjs +10 -1
- package/dist/esm/components/Loading/index.mjs.map +1 -1
- package/dist/esm/components/Path/index.mjs +1 -1
- package/dist/esm/components/Path/index.mjs.map +1 -1
- package/dist/esm/components/Rect/index.mjs +1 -1
- package/dist/esm/components/Rect/index.mjs.map +1 -1
- package/dist/esm/components/StoreUpdater/index.mjs +1 -1
- package/dist/esm/components/StoreUpdater/index.mjs.map +1 -1
- package/dist/esm/components/Text/index.mjs +1 -1
- package/dist/esm/components/Text/index.mjs.map +1 -1
- package/dist/esm/components/Textbox/index.mjs +1 -1
- package/dist/esm/components/Textbox/index.mjs.map +1 -1
- package/dist/esm/components/WavyLine/index.mjs +1 -1
- package/dist/esm/components/WavyLine/index.mjs.map +1 -1
- package/dist/esm/container/ReactFabric/index.mjs +1 -1
- package/dist/esm/container/ReactFabric/index.mjs.map +1 -1
- package/dist/esm/hooks/useInstancePosition.mjs +2 -0
- package/dist/esm/hooks/useInstancePosition.mjs.map +1 -0
- package/dist/esm/hooks/useReactFabric.mjs +1 -1
- package/dist/esm/hooks/useReactFabric.mjs.map +1 -1
- package/dist/esm/hooks/useStore.mjs +1 -1
- package/dist/esm/hooks/useStore.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/plugins/FreeDraw.mjs +2 -0
- package/dist/esm/plugins/FreeDraw.mjs.map +1 -0
- package/dist/esm/plugins/FreeText.mjs +2 -0
- package/dist/esm/plugins/FreeText.mjs.map +1 -0
- package/dist/esm/store/index.mjs +1 -1
- package/dist/esm/store/index.mjs.map +1 -1
- package/dist/esm/store/initialState.mjs +1 -1
- package/dist/esm/store/initialState.mjs.map +1 -1
- package/dist/esm/utils/business.mjs +2 -0
- package/dist/esm/utils/business.mjs.map +1 -0
- package/dist/esm/utils/childrenWithPosition.mjs +2 -0
- package/dist/esm/utils/childrenWithPosition.mjs.map +1 -0
- package/dist/esm/utils/constants.mjs +1 -1
- package/dist/esm/utils/constants.mjs.map +1 -1
- package/dist/esm/utils/dom.mjs +2 -0
- package/dist/esm/utils/dom.mjs.map +1 -0
- package/dist/esm/utils/position.mjs +2 -0
- package/dist/esm/utils/position.mjs.map +1 -0
- package/dist/esm/utils/props.mjs +1 -1
- package/dist/esm/utils/props.mjs.map +1 -1
- package/dist/types/components/BackgroundImage/index.d.ts.map +1 -1
- package/dist/types/components/Canvas/index.d.ts.map +1 -1
- package/dist/types/components/Control2/index.d.ts +28 -0
- package/dist/types/components/Control2/index.d.ts.map +1 -0
- package/dist/types/components/Ellipse/index.d.ts.map +1 -1
- package/dist/types/components/Group/index.d.ts.map +1 -1
- package/dist/types/components/IText/index.d.ts.map +1 -1
- package/dist/types/components/Image/index.d.ts +4 -4
- package/dist/types/components/Image/index.d.ts.map +1 -1
- package/dist/types/components/Line/index.d.ts.map +1 -1
- package/dist/types/components/Loading/index.d.ts.map +1 -1
- package/dist/types/components/Path/index.d.ts.map +1 -1
- package/dist/types/components/Polyline/index.d.ts.map +1 -1
- package/dist/types/components/Rect/index.d.ts.map +1 -1
- package/dist/types/components/StoreUpdater/index.d.ts +1 -1
- package/dist/types/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/types/components/Text/index.d.ts.map +1 -1
- package/dist/types/components/Textbox/index.d.ts.map +1 -1
- package/dist/types/components/WavyLine/index.d.ts.map +1 -1
- package/dist/types/container/ReactFabric/index.d.ts +4 -0
- package/dist/types/container/ReactFabric/index.d.ts.map +1 -1
- package/dist/types/hooks/useInstancePosition.d.ts +12 -0
- package/dist/types/hooks/useInstancePosition.d.ts.map +1 -0
- package/dist/types/hooks/useReactFabric.d.ts +2 -1
- package/dist/types/hooks/useReactFabric.d.ts.map +1 -1
- package/dist/types/index.d.ts +7 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/plugins/index.d.ts +1 -0
- package/dist/types/plugins/index.d.ts.map +1 -1
- package/dist/types/store/index.d.ts.map +1 -1
- package/dist/types/store/initialState.d.ts.map +1 -1
- package/dist/types/types/component-props.d.ts +0 -35
- package/dist/types/types/component-props.d.ts.map +1 -1
- package/dist/types/types/store.d.ts +13 -0
- package/dist/types/types/store.d.ts.map +1 -1
- package/dist/types/utils/childrenWithPosition.d.ts +6 -0
- package/dist/types/utils/childrenWithPosition.d.ts.map +1 -0
- package/package.json +13 -6
- package/dist/cjs/hooks/useChildrenPosition.cjs +0 -2
- package/dist/cjs/hooks/useChildrenPosition.cjs.map +0 -1
- package/dist/esm/hooks/useChildrenPosition.mjs +0 -2
- package/dist/esm/hooks/useChildrenPosition.mjs.map +0 -1
- package/dist/types/hooks/useChildrenPosition.d.ts +0 -8
- package/dist/types/hooks/useChildrenPosition.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/WavyLine/index.tsx"],"sourcesContent":["/* eslint-disable prefer-const */\nimport type { Group as BaseGroup } from 'fabric'\nimport { Line as BaseLine, Point } from 'fabric'\nimport {
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/WavyLine/index.tsx"],"sourcesContent":["/* eslint-disable prefer-const */\nimport type { Group as BaseGroup } from 'fabric'\nimport { Line as BaseLine, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\ninterface UniqueLineProps {\n x1: number\n x2: number\n y1: number\n y2: number\n}\n\nclass WavyLineClass extends BaseLine {\n static type = 'wavyLine'\n\n constructor(points: any, options = {}) {\n super(points, options)\n }\n\n _render(ctx: any) {\n /** 参考 Line 源码改造,可能不完整 https://github.com/fabricjs/fabric.js/blob/e114448a1bce9b68a3e1bba337bc0c83a35c1aa5/src/shapes/Line.ts#L29 */\n ctx.beginPath()\n\n const p = this.calcLinePoints()\n const point = this.pointOnLine(this.point(p.x2, p.y2))\n this.wavy(this.point(p.x1, p.y1), point, ctx)\n ctx.lineWidth = this.strokeWidth\n const origStrokeStyle = ctx.strokeStyle\n ctx.strokeStyle = this.stroke ?? ctx.fillStyle\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n this.stroke && this._renderStroke(ctx)\n ctx.strokeStyle = origStrokeStyle\n }\n\n point(x: any, y: any) {\n return {\n x: x,\n y: y,\n }\n }\n\n wavy(from: any, to: any, ctx: any) {\n const wavyWidth = 4 * 3\n let cx = 0,\n cy = 0,\n fx = from.x,\n fy = from.y,\n tx = to.x,\n ty = to.y,\n i = 0,\n step = 1,\n waveOffsetLength = 0,\n ang = Math.atan2(ty - fy, tx - fx),\n distance = Math.sqrt((fx - tx) * (fx - tx) + (fy - ty) * (fy - ty)),\n amplitude = -1 * 2,\n f = (Math.PI * distance) / wavyWidth\n for (i; i <= distance; i += step) {\n waveOffsetLength = Math.sin((i / distance) * f) * amplitude\n cx = from.x + Math.cos(ang) * i + Math.cos(ang - Math.PI / 2) * waveOffsetLength\n cy = from.y + Math.sin(ang) * i + Math.sin(ang - Math.PI / 2) * waveOffsetLength\n\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n i > 0 ? ctx.lineTo(cx, cy) : ctx.moveTo(cx, cy)\n }\n }\n\n pointOnLine(point1: any) {\n const x3 = point1.x,\n y3 = point1.y\n return new Point(x3, y3)\n }\n\n calcLinePoints(): UniqueLineProps {\n const { x1: _x1, x2: _x2, y1: _y1, y2: _y2, width, height } = this\n const xMult = _x1 <= _x2 ? -1 : 1,\n yMult = _y1 <= _y2 ? -1 : 1,\n x1 = (xMult * width) / 2,\n y1 = (yMult * height) / 2,\n x2 = (xMult * -width) / 2,\n y2 = (yMult * -height) / 2\n\n return {\n x1,\n x2,\n y1,\n y2,\n }\n }\n\n toObject(propertiesToInclude = []) {\n const obj = super.toObject(propertiesToInclude)\n return { ...obj } as any\n }\n}\n\nexport type WavyLineProps<T = unknown> = Partial<ConstructorParameters<typeof BaseLine>[1] & AllObjectEvents> & {\n group?: BaseGroup\n path?: string\n children?: ReactNode\n} & T\n\nconst WavyLine = forwardRef<BaseLine | undefined, WavyLineProps>(\n ({ group, x1, y1, x2, y2, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: WavyLineClass,\n param: [x1, y1, x2, y2],\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n },\n)\n\nexport default memo(WavyLine)\n"],"names":["WavyLineClass","BaseLine","points","options","ctx","p","point","origStrokeStyle","x","y","from","to","cx","cy","fx","fy","tx","ty","i","step","waveOffsetLength","ang","distance","amplitude","f","point1","x3","y3","Point","_x1","_x2","_y1","_y2","width","height","xMult","yMult","x1","y1","x2","y2","propertiesToInclude","__publicField","WavyLine","forwardRef","group","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","memo"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),a=require("react"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),a=require("react"),Z=require("./Wrapper.cjs"),q=require("../../components/Canvas/index.cjs"),y=require("../../components/StoreUpdater/index.cjs"),D=require("../../components/Loading/index.cjs");const W={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},z=a.forwardRef(({minManualZoom:r,maxManualZoom:l,className:n,children:i,width:t,height:u,selection:d,style:s,onMouseWheel:m,onMouseDown:c,onMouseMove:h,onMouseUp:f,zoomable:M,panAble:x,defaultSelection:p,defaultCentered:v,defaultDraggable:b,manualZoom:g,...j},w)=>e.jsx("div",{style:{...W,...s},ref:w,className:`react-fabric ${n||""}`,children:e.jsxs(Z.Wrapper,{width:t,height:u,children:[e.jsx(y.StoreUpdater,{minManualZoom:r,maxManualZoom:l,zoomable:M,panAble:x,defaultCentered:v,selection:d,defaultSelection:p,defaultDraggable:b,manualZoom:g}),e.jsx(q.default,{onMouseDown:c,onMouseMove:h,onMouseUp:f,onMouseWheel:m,...j,children:i}),e.jsx(D.default,{})]})})),o=a.memo(z);o.displayName="ReactFabric",exports.default=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\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\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={{ ...wrapperStyle, ...style }} 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":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\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\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 panAble?: boolean\n manualZoom?: number\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 panAble,\n defaultSelection,\n defaultCentered,\n defaultDraggable,\n manualZoom,\n ...rest\n },\n ref,\n ) => {\n return (\n <div style={{ ...wrapperStyle, ...style }} ref={ref} className={`react-fabric ${className || ''}`}>\n <Wrapper width={width} height={height}>\n <StoreUpdater\n minManualZoom={minManualZoom}\n maxManualZoom={maxManualZoom}\n zoomable={zoomable}\n panAble={panAble}\n defaultCentered={defaultCentered}\n selection={selection}\n defaultSelection={defaultSelection}\n defaultDraggable={defaultDraggable}\n manualZoom={manualZoom}\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","panAble","defaultSelection","defaultCentered","defaultDraggable","manualZoom","rest","ref","jsx","jsxs","Wrapper","StoreUpdater","Canvas","Loading","ReactFabric","memo"],"mappings":"+SA2BMA,EAA8B,CAClC,MAAO,OACP,OAAQ,OACR,SAAU,SACV,SAAU,WACV,OAAQ,CACV,EA4BMC,EAAqBC,EAAAA,WACzB,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,QAAAC,EACA,iBAAAC,EACA,gBAAAC,EACA,iBAAAC,EACA,WAAAC,EACA,GAAGC,CACL,EACAC,IAGEC,EAAC,IAAA,MAAA,CAAI,MAAO,CAAE,GAAGvB,EAAc,GAAGU,CAAM,EAAG,IAAKY,EAAK,UAAW,gBAAgBjB,GAAa,EAAE,GAC7F,SAAAmB,EAACC,KAAAA,EAAAA,QAAA,CAAQ,MAAOlB,EAAO,OAAQC,EAC7B,UAAAe,EAACG,IAAAA,EAAAA,aAAA,CACC,cAAevB,EACf,cAAeC,EACf,SAAUW,EACV,QAASC,EACT,gBAAiBE,EACjB,UAAWT,EACX,iBAAkBQ,EAClB,iBAAkBE,EAClB,WAAYC,EACd,EAEAG,EAAAA,IAACI,EAAAA,QAAA,CACC,YAAaf,EACb,YAAaC,EACb,UAAWC,EACX,aAAcH,EACb,GAAGU,EAEH,SAAAf,CACH,CAAA,EACAiB,EAAAA,IAACK,EAAAA,QAAA,CAAA,CAAQ,CACX,CAAA,CAAA,CAAA,CACF,CAGN,EAIMC,EAAoCC,EAAK7B,KAAAA,CAAkB,EACjE4B,EAAY,YAAc"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var n=require("react"),$=require("fabric"),d=require("./useStore.cjs");function v(o,s){const c=d.useStoreApi(),u=n.useRef(null),f=n.useRef("");if(n.useEffect(()=>{if(!o)return;const{canvas:t}=c.getState();if(!t)return;const i=()=>{if(!u.current)return;const e=o.getCoords().map(x=>$.util.sendPointToPlane(x,t.viewportTransform,void 0)),l=`${e[0].x},${e[0].y},${e[2].x-e[0].x},${e[2].y-e[0].y}`;if(l===f.current)return;f.current=l;const y=u.current;Object.assign(y.style,{position:"absolute",left:`${e[0].x}px`,top:`${e[0].y}px`,width:`${e[2].x-e[0].x}px`,height:`${e[2].y-e[0].y}px`})};return t.on("after:render",i),i(),()=>{t.off("after:render",i)}},[o,c]),!n.isValidElement(s))return s;const a=s.props,r=s.ref,p=n.useCallback(t=>{u.current=t,r&&(typeof r=="function"?r(t):r&&(r.current=t))},[r]);return n.cloneElement(s,{...a,ref:p,style:{position:"absolute",...a.style}})}exports.useInstancePosition=v;
|
|
2
|
+
//# sourceMappingURL=useInstancePosition.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInstancePosition.cjs","sources":["../../../src/hooks/useInstancePosition.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, cloneElement, isValidElement, type ReactNode } from 'react'\nimport { util } from 'fabric'\nimport type { FabricObject } from 'fabric'\nimport { useStoreApi } from './useStore'\n\n/**\n * 用于同步子元素位置与 Fabric.js 对象位置的 Hook\n * 直接操作 DOM 元素样式,避免频繁的 React 重渲染\n * 同时处理 ref 合并和 children 克隆\n * @param instance Fabric.js 对象实例\n * @param children 需要处理的子元素\n * @returns 处理后的 children\n */\nexport function useInstancePosition(instance: FabricObject | undefined, children: ReactNode) {\n const store = useStoreApi()\n const childElementRef = useRef<HTMLElement | null>(null)\n const lastPositionRef = useRef<string>('')\n\n useEffect(() => {\n if (!instance) return\n\n const { canvas } = store.getState()\n if (!canvas) return\n\n const updatePosition = () => {\n if (!childElementRef.current) return\n\n const sceneCoords = instance.getCoords()\n const viewportCoords = sceneCoords.map(point => util.sendPointToPlane(point, canvas.viewportTransform, undefined))\n\n const newPosition = `${viewportCoords[0].x},${viewportCoords[0].y},${viewportCoords[2].x - viewportCoords[0].x},${viewportCoords[2].y - viewportCoords[0].y}`\n\n if (newPosition === lastPositionRef.current) return\n lastPositionRef.current = newPosition\n\n const element = childElementRef.current\n Object.assign(element.style, {\n position: 'absolute',\n left: `${viewportCoords[0].x}px`,\n top: `${viewportCoords[0].y}px`,\n width: `${viewportCoords[2].x - viewportCoords[0].x}px`,\n height: `${viewportCoords[2].y - viewportCoords[0].y}px`,\n })\n }\n\n canvas.on('after:render', updatePosition)\n updatePosition()\n\n return () => {\n canvas.off('after:render', updatePosition)\n }\n }, [instance, store])\n\n // 处理 children\n if (!isValidElement(children)) return children\n\n const childProps = children.props as any\n const originalRef = (children as any).ref\n\n const handleRef = useCallback(\n (node: any) => {\n childElementRef.current = node\n if (originalRef) {\n if (typeof originalRef === 'function') {\n originalRef(node)\n } else if (originalRef) {\n originalRef.current = node\n }\n }\n },\n [originalRef],\n )\n\n return cloneElement(children, {\n ...childProps,\n ref: handleRef,\n style: {\n position: 'absolute',\n ...childProps.style,\n },\n } as any)\n}\n"],"names":["useInstancePosition","instance","children","store","useStoreApi","childElementRef","useRef","lastPositionRef","useEffect","canvas","updatePosition","viewportCoords","point","util","newPosition","element","isValidElement","childProps","originalRef","handleRef","useCallback","node","cloneElement"],"mappings":"oFAaO,SAASA,EAAoBC,EAAoCC,EAAqB,CAC3F,MAAMC,EAAQC,EAAY,YAAA,EACpBC,EAAkBC,SAA2B,IAAI,EACjDC,EAAkBD,EAAe,OAAA,EAAE,EAsCzC,GApCAE,EAAU,UAAA,IAAM,CACd,GAAI,CAACP,EAAU,OAEf,KAAM,CAAE,OAAAQ,CAAO,EAAIN,EAAM,SAAA,EACzB,GAAI,CAACM,EAAQ,OAEb,MAAMC,EAAiB,IAAM,CAC3B,GAAI,CAACL,EAAgB,QAAS,OAG9B,MAAMM,EADcV,EAAS,YACM,IAAIW,GAASC,OAAK,iBAAiBD,EAAOH,EAAO,kBAAmB,MAAS,CAAC,EAE3GK,EAAc,GAAGH,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IAAIA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,GAE3J,GAAIG,IAAgBP,EAAgB,QAAS,OAC7CA,EAAgB,QAAUO,EAE1B,MAAMC,EAAUV,EAAgB,QAChC,OAAO,OAAOU,EAAQ,MAAO,CAC3B,SAAU,WACV,KAAM,GAAGJ,EAAe,CAAC,EAAE,CAAC,KAC5B,IAAK,GAAGA,EAAe,CAAC,EAAE,CAAC,KAC3B,MAAO,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,KACnD,OAAQ,GAAGA,EAAe,CAAC,EAAE,EAAIA,EAAe,CAAC,EAAE,CAAC,IACtD,CAAC,CACH,EAEA,OAAAF,EAAO,GAAG,eAAgBC,CAAc,EACxCA,IAEO,IAAM,CACXD,EAAO,IAAI,eAAgBC,CAAc,CAC3C,CACF,EAAG,CAACT,EAAUE,CAAK,CAAC,EAGhB,CAACa,iBAAed,CAAQ,EAAG,OAAOA,EAEtC,MAAMe,EAAaf,EAAS,MACtBgB,EAAehB,EAAiB,IAEhCiB,EAAYC,EAAAA,YACfC,GAAc,CACbhB,EAAgB,QAAUgB,EACtBH,IACE,OAAOA,GAAgB,WACzBA,EAAYG,CAAI,EACPH,IACTA,EAAY,QAAUG,GAG5B,EACA,CAACH,CAAW,CACd,EAEA,OAAOI,eAAapB,EAAU,CAC5B,GAAGe,EACH,IAAKE,EACL,MAAO,CACL,SAAU,WACV,GAAGF,EAAW,KAChB,CACF,CAAQ,CACV"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var d=require("zustand/vanilla/shallow"),r=require("react"),u=require("./useStore.cjs");const S=e=>({draggable:e.draggable,selection:e.selection,isDragging:e.isDragging,width:e.width,height:e.height,canvas:e.canvas,setDraggable:e.setDraggable,setIsDragging:e.setIsDragging,lastPosX:e.lastPosX,lastPosY:e.lastPosY,setSelection:e.setSelection,zoomable:e.zoomable,setZoomable:e.setZoomable,scale:e.scale,zoom:e.zoom,fitZoom:e.fitZoom,defaultCentered:e.defaultCentered,manualZoom:e.manualZoom,maxManualZoom:e.maxManualZoom,minManualZoom:e.minManualZoom,loading:e.loading});function f(){const e=u.useStoreApi(),i=u.useStore(S,d.shallow),l=r.useMemo(()=>({getCanvas:()=>e.getState().canvas,getNodes:()=>e.getState().nodes.map(o=>({...o})),getState:()=>e.getState,zoomIn:()=>{let{manualZoom:o,canvas:a,fitZoom:m}=e.getState();o+=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const s=o*m;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,s)}e.setState({manualZoom:o,zoom:s})},zoomOut:()=>{let{manualZoom:o,canvas:a,fitZoom:m}=e.getState();o-=.2;const n=e.getState().maxManualZoom,t=e.getState().minManualZoom;o>n&&(o=n),o<t&&(o=t);const s=o*m;if(a?.backgroundImage&&a){const g=a.getCenterPoint();a.zoomToPoint(g,s)}e.setState({manualZoom:o,zoom:s})},getZoom:()=>e.getState().zoom,resetViewport:(o=1)=>{const{canvas:a,fitZoom:m=1,defaultCentered:n}=e.getState(),t=o*m;if(a){if(n&&a.backgroundImage){const s=a.backgroundImage.width||0,g=a.backgroundImage.height||0,c=(a.width-s*t)/2,Z=(a.height-g*t)/2;a.setViewportTransform([t,0,0,t,c,Z])}else a.setViewportTransform([t,0,0,t,0,0]);a.requestRenderAll()}e.setState({manualZoom:o,zoom:t})}}),[e]);return r.useMemo(()=>({...l,...i}),[l,i])}exports.useReactFabric=f;
|
|
2
2
|
//# sourceMappingURL=useReactFabric.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReactFabric.cjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: () => {\n
|
|
1
|
+
{"version":3,"file":"useReactFabric.cjs","sources":["../../../src/hooks/useReactFabric.ts"],"sourcesContent":["import { shallow } from 'zustand/vanilla/shallow'\nimport { useMemo } from 'react'\nimport type { ReactFabricState } from '../types/store'\nimport { useStore, useStoreApi } from './useStore'\n\nconst selector = (s: ReactFabricState) => ({\n draggable: s.draggable,\n selection: s.selection,\n isDragging: s.isDragging,\n width: s.width,\n height: s.height,\n canvas: s.canvas,\n setDraggable: s.setDraggable,\n setIsDragging: s.setIsDragging,\n lastPosX: s.lastPosX,\n lastPosY: s.lastPosY,\n setSelection: s.setSelection,\n zoomable: s.zoomable,\n setZoomable: s.setZoomable,\n scale: s.scale,\n zoom: s.zoom,\n fitZoom: s.fitZoom,\n defaultCentered: s.defaultCentered,\n manualZoom: s.manualZoom,\n maxManualZoom: s.maxManualZoom,\n minManualZoom: s.minManualZoom,\n loading: s.loading,\n})\n\nexport function useReactFabric() {\n const store = useStoreApi()\n const state = useStore(selector, shallow)\n\n const generalHelper = useMemo(() => {\n return {\n getCanvas: () => store.getState().canvas,\n getNodes: () => store.getState().nodes.map(n => ({ ...n })),\n getState: () => store.getState,\n\n /**\n * 放大\n */\n zoomIn: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom += 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n\n /**\n * 缩小\n */\n zoomOut: () => {\n let { manualZoom, canvas, fitZoom } = store.getState()\n manualZoom -= 0.2\n const maxManualZoom = store.getState().maxManualZoom\n const minManualZoom = store.getState().minManualZoom\n if (manualZoom > maxManualZoom) manualZoom = maxManualZoom\n if (manualZoom < minManualZoom) manualZoom = minManualZoom\n\n const combinedZoom = manualZoom * fitZoom\n const bgImage = canvas?.backgroundImage\n if (bgImage && canvas) {\n // 返回画布的中心点,这个点是固定的 不受背景图位置和变换的影响\n const center = canvas.getCenterPoint()\n canvas.zoomToPoint(center, combinedZoom)\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n getZoom: () => store.getState().zoom,\n\n /**\n * 重置视口/缩放\n */\n resetViewport: (manualZoom = 1) => {\n const { canvas, fitZoom = 1, defaultCentered } = store.getState()\n\n const combinedZoom = manualZoom * fitZoom\n if (canvas) {\n // 先重置 viewport transform\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n const deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n const deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, deltaX, deltaY])\n } else {\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n }\n canvas.requestRenderAll()\n }\n\n store.setState({\n manualZoom: manualZoom,\n zoom: combinedZoom,\n })\n },\n }\n }, [store])\n\n return useMemo(\n () => ({\n ...generalHelper,\n ...state,\n }),\n [generalHelper, state],\n )\n}\n"],"names":["selector","s","useReactFabric","store","useStoreApi","state","useStore","shallow","generalHelper","useMemo","n","manualZoom","canvas","fitZoom","maxManualZoom","minManualZoom","combinedZoom","center","defaultCentered","bgWidth","bgHeight","deltaX","deltaY"],"mappings":"qGAKA,MAAMA,EAAYC,IAAyB,CACzC,UAAWA,EAAE,UACb,UAAWA,EAAE,UACb,WAAYA,EAAE,WACd,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,OAAQA,EAAE,OACV,aAAcA,EAAE,aAChB,cAAeA,EAAE,cACjB,SAAUA,EAAE,SACZ,SAAUA,EAAE,SACZ,aAAcA,EAAE,aAChB,SAAUA,EAAE,SACZ,YAAaA,EAAE,YACf,MAAOA,EAAE,MACT,KAAMA,EAAE,KACR,QAASA,EAAE,QACX,gBAAiBA,EAAE,gBACnB,WAAYA,EAAE,WACd,cAAeA,EAAE,cACjB,cAAeA,EAAE,cACjB,QAASA,EAAE,OACb,YAEgBC,GAAiB,CAC/B,MAAMC,EAAQC,EAAAA,YAAAA,EACRC,EAAQC,EAAAA,SAASN,EAAUO,SAAO,EAElCC,EAAgBC,EAAAA,QAAQ,KACrB,CACL,UAAW,IAAMN,EAAM,WAAW,OAClC,SAAU,IAAMA,EAAM,SAAA,EAAW,MAAM,IAAIO,IAAM,CAAE,GAAGA,CAAE,EAAE,EAC1D,SAAU,IAAMP,EAAM,SAKtB,OAAQ,IAAM,CACZ,GAAI,CAAE,WAAAQ,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EAKA,QAAS,IAAM,CACb,GAAI,CAAE,WAAAL,EAAY,OAAAC,EAAQ,QAAAC,CAAQ,EAAIV,EAAM,WAC5CQ,GAAc,GACd,MAAMG,EAAgBX,EAAM,SAAA,EAAW,cACjCY,EAAgBZ,EAAM,SAAS,EAAE,cACnCQ,EAAaG,IAAeH,EAAaG,GACzCH,EAAaI,IAAeJ,EAAaI,GAE7C,MAAMC,EAAeL,EAAaE,EAElC,GADgBD,GAAQ,iBACTA,EAAQ,CAErB,MAAMK,EAASL,EAAO,eAAe,EACrCA,EAAO,YAAYK,EAAQD,CAAY,CACzC,CAEAb,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,EACA,QAAS,IAAMb,EAAM,WAAW,KAKhC,cAAe,CAACQ,EAAa,IAAM,CACjC,KAAM,CAAE,OAAAC,EAAQ,QAAAC,EAAU,EAAG,gBAAAK,CAAgB,EAAIf,EAAM,SAAS,EAE1Da,EAAeL,EAAaE,EAClC,GAAID,EAAQ,CAEV,GAAIM,GAAmBN,EAAO,gBAAiB,CAC7C,MAAMO,EAAUP,EAAO,gBAAgB,OAAS,EAC1CQ,EAAWR,EAAO,gBAAgB,QAAU,EAC5CS,GAAUT,EAAO,MAASO,EAAUH,GAAgB,EACpDM,GAAUV,EAAO,OAAUQ,EAAWJ,GAAgB,EAC5DJ,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAcK,EAAQC,CAAM,CAAC,CAChF,MACEV,EAAO,qBAAqB,CAACI,EAAc,EAAG,EAAGA,EAAc,EAAG,CAAC,CAAC,EAEtEJ,EAAO,kBACT,CAEAT,EAAM,SAAS,CACb,WAAYQ,EACZ,KAAMK,CACR,CAAC,CACH,CACF,GACC,CAACb,CAAK,CAAC,EAEV,OAAOM,EAAAA,QACL,KAAO,CACL,GAAGD,EACH,GAAGH,CACL,GACA,CAACG,EAAeH,CAAK,CACvB,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var t=require("react"),n=require("zustand/traditional"),u=require("../contexts/StoreContext.cjs");function o(e,s){const r=t.useContext(u.default);if(r===null)throw new Error("useReactFabric \u9700\u8981\u642D\u914D zustandProvider");return n.useStoreWithEqualityFn(r,e,s)}function i(){const e=t.useContext(u.default);if(e===null)throw new Error("\u7F3A\u5931zustandProvider");return t.useMemo(()=>({getState:e.getState,setState:e.setState,subscribe:e.subscribe}),[e])}exports.useStore=o,exports.useStoreApi=i;
|
|
2
2
|
//# sourceMappingURL=useStore.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStore.cjs","sources":["../../../src/hooks/useStore.ts"],"sourcesContent":["import { useContext, useMemo } from 'react'\nimport type { StoreApi } from 'zustand'\nimport type { UseBoundStoreWithEqualityFn } from 'zustand/traditional'\nimport { useStoreWithEqualityFn as useZustandStore } from 'zustand/traditional'\nimport StoreContext from '../contexts/StoreContext'\nimport type { Node } from '../types/nodes'\nimport type { ReactFabricState } from '../types/store'\n\nfunction useStore<StateSlice = unknown>(\n selector: (state: ReactFabricState) => StateSlice,\n equalityFn?: (a: StateSlice, b: StateSlice) => boolean,\n) {\n const store = useContext(StoreContext)\n\n if (store === null) {\n throw new Error('
|
|
1
|
+
{"version":3,"file":"useStore.cjs","sources":["../../../src/hooks/useStore.ts"],"sourcesContent":["import { useContext, useMemo } from 'react'\nimport type { StoreApi } from 'zustand'\nimport type { UseBoundStoreWithEqualityFn } from 'zustand/traditional'\nimport { useStoreWithEqualityFn as useZustandStore } from 'zustand/traditional'\nimport StoreContext from '../contexts/StoreContext'\nimport type { Node } from '../types/nodes'\nimport type { ReactFabricState } from '../types/store'\n\nfunction useStore<StateSlice = unknown>(\n selector: (state: ReactFabricState) => StateSlice,\n equalityFn?: (a: StateSlice, b: StateSlice) => boolean,\n) {\n const store = useContext(StoreContext)\n\n if (store === null) {\n throw new Error('useReactFabric 需要搭配 zustandProvider')\n }\n\n return useZustandStore(store, selector, equalityFn)\n}\n\nfunction useStoreApi<NodeType extends Node = Node>() {\n const store = useContext(StoreContext) as UseBoundStoreWithEqualityFn<StoreApi<ReactFabricState<NodeType>>> | null\n\n if (store === null) {\n throw new Error('缺失zustandProvider')\n }\n\n return useMemo(\n () => ({\n getState: store.getState,\n setState: store.setState,\n subscribe: store.subscribe,\n }),\n [store],\n )\n}\n\nexport { useStore, useStoreApi }\n"],"names":["useStore","selector","equalityFn","store","useContext","StoreContext","useZustandStore","useStoreApi","useMemo"],"mappings":"+GAQA,SAASA,EACPC,EACAC,EACA,CACA,MAAMC,EAAQC,aAAWC,SAAY,EAErC,GAAIF,IAAU,KACZ,MAAM,IAAI,MAAM,yDAAqC,EAGvD,OAAOG,EAAAA,uBAAgBH,EAAOF,EAAUC,CAAU,CACpD,CAEA,SAASK,GAA4C,CACnD,MAAMJ,EAAQC,EAAWC,WAAAA,SAAY,EAErC,GAAIF,IAAU,KACZ,MAAM,IAAI,MAAM,6BAAmB,EAGrC,OAAOK,UACL,KAAO,CACL,SAAUL,EAAM,SAChB,SAAUA,EAAM,SAChB,UAAWA,EAAM,SACnB,GACA,CAACA,CAAK,CACR,CACF"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("./container/ReactFabric/index.cjs"),r=require("./hooks/useReactFabric.cjs"),a=require("./hooks/useZoom.cjs"),i=require("./components/BackgroundImage/index.cjs"),u=require("./components/Canvas/index.cjs"),d=require("./components/Group/index.cjs"),t=require("./components/NodeToolbarPortal/index.cjs"),l=require("./components/ReactFabricProvider.cjs"),n=require("./components/Rect/index.cjs"),v=require("./components/Control/index.cjs"),c=require("./components/Text/index.cjs"),
|
|
1
|
+
"use strict";var e=require("./container/ReactFabric/index.cjs"),r=require("./hooks/useReactFabric.cjs"),a=require("./hooks/useZoom.cjs"),i=require("./components/BackgroundImage/index.cjs"),u=require("./components/Canvas/index.cjs"),d=require("./components/Group/index.cjs"),t=require("./components/NodeToolbarPortal/index.cjs"),l=require("./components/ReactFabricProvider.cjs"),n=require("./components/Rect/index.cjs"),v=require("./components/Control/index.cjs"),q=require("./components/Image/index.cjs"),f=require("./components/Control2/index.cjs"),c=require("./components/Text/index.cjs"),x=require("./components/Path/index.cjs"),o=require("./components/Line/index.cjs"),$=require("./components/Ellipse/index.cjs"),s=require("./components/IText/index.cjs"),F=require("./components/Textbox/index.cjs"),P=require("./components/WavyLine/index.cjs"),b=require("./components/Objects/index.cjs"),g=require("./plugins/FreeRect.cjs"),R=require("./plugins/GridLine.cjs"),T=require("./plugins/Pinch.cjs"),m=require("./plugins/FreeDraw.cjs"),h=require("./plugins/FreeText.cjs"),k=require("./plugins/Mask.cjs");exports.ReactFabric=e.default,exports.useReactFabric=r.useReactFabric,exports.useZoom=a.useZoom,exports.BackgroundImage=i.default,exports.Canvas=u.default,exports.Group=d.default,exports.NodeToolbarPortal=t.default,exports.ReactFabricProvider=l.ReactFabricProvider,exports.Rect=n.default,exports.Control=v.default,exports.Image=q.default,exports.Control2=f.default,exports.Text=c.default,exports.Path=x.default,exports.Line=o.default,exports.Ellipse=$.default,exports.IText=s.default,exports.Textbox=F.default,exports.WavyLine=P.default,exports.Objects=b.default,exports.PluginFreeRect=g.default,exports.PluginGrid=R.default,exports.PluginPinch=T.default,exports.PluginFreeDraw=m.default,exports.PluginFreeText=h.default,exports.PluginMask=k.default;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("./FreeRect.cjs"),r=require("./GridLine.cjs"),
|
|
1
|
+
"use strict";var e=require("./FreeRect.cjs"),r=require("./GridLine.cjs"),u=require("./Pinch.cjs"),i=require("./FreeDraw.cjs"),a=require("./FreeText.cjs"),l=require("./Mask.cjs");exports.PluginFreeRect=e.default,exports.PluginGrid=r.default,exports.PluginPinch=u.default,exports.PluginFreeDraw=i.default,exports.PluginFreeText=a.default,exports.PluginMask=l.default;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/cjs/store/index.cjs
CHANGED
|
@@ -1,2 +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,
|
|
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,t)=>({...l.default({nodes:n,width:u,height:g,defaultNodes:r}),setDimensions:e=>{const{width:o,height:d}=e,s=t(),i={width:o??s.width,height:d??s.height};t().canvas?.setDimensions(i),a(i)},setLoading:e=>{a({loading:e})},setDraggable:e=>{a({draggable:e});const o=t().canvas;o&&(o.setCursor(e?"grab":"default"),o.hoverCursor=e?"grab":"default",o.requestRenderAll())},setZoomable:e=>{a({zoomable:e})},setIsDragging:e=>{a({isDragging:e})},setSelection:e=>{const o=t().canvas;o&&(a({selection:e}),o.set("selection",e),o.requestRenderAll())},setDefaultDraggable:e=>{if(e===void 0)return;const{setDraggable:o}=t();a({hasDefaultDraggable:!0}),o(e)},setDefaultSelection:e=>{if(e===void 0)return;const{setSelection:o}=t();a({hasDefaultSelection:!0}),o(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})},setControls:e=>{a({controls:e})},reset:()=>a({...l.default()})}),Object.is);exports.createStore=h;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +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,
|
|
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 setControls: (controls) => {\n set({ controls })\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","controls"],"mappings":"kFAKMA,MAAAA,EAAc,CAAC,CACnB,MAAAC,EACA,aAAAC,EACA,MAAAC,EACA,OAAAC,CACF,IAMEC,EACE,qBAAA,CAACC,EAAKC,KAAS,CACb,GAAGC,EAAAA,QAAgB,CAAE,MAAAP,EAAO,MAAAE,EAAO,OAAAC,EAAQ,aAAAF,CAAa,CAAC,EACzD,cAAgBO,GAAiD,CAC/D,KAAM,CAAE,MAAAN,EAAO,OAAAC,CAAO,EAAIK,EACpBC,EAAeH,IAGfI,EAAgB,CACpB,MAAOR,GAASO,EAAa,MAC7B,OAAQN,GAAUM,EAAa,MACjC,EAEAH,EAAM,EAAA,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,EAAAA,EAAM,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,EAAI,EAAE,OAChBO,IACLR,EAAI,CAAE,UAAAW,CAAU,CAAC,EACjBH,EAAO,IAAI,YAAaG,CAAS,EACjCH,EAAO,mBACT,EACA,oBAAqBI,GAAoB,CACvC,GAAIA,IAAqB,OAAW,OACpC,KAAM,CAAE,aAAAC,CAAa,EAAIZ,EAAAA,EACzBD,EAAI,CAAE,oBAAqB,EAAK,CAAC,EACjCa,EAAaD,CAAgB,CAC/B,EACA,oBAAqBE,GAAoB,CACvC,GAAIA,IAAqB,OAAW,OACpC,KAAM,CAAE,aAAAC,CAAa,EAAId,EAAAA,EACzBD,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,EACA,YAAcC,GAAa,CACzBnB,EAAI,CAAE,SAAAmB,CAAS,CAAC,CAClB,EACA,MAAO,IAAMnB,EAAI,CAAE,GAAGE,EAAgB,QAAA,CAAE,CAAC,CAC3C,GACA,OAAO,EACT"}
|
|
@@ -1,2 +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;
|
|
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,panAble:!0,draggable:!1,scale:1,lastPosX:void 0,lastPosY:void 0,loading:!1,fitZoom:1,manualZoom:1,defaultCentered:!1,controls:[]});exports.default=d;
|
|
2
2
|
//# sourceMappingURL=initialState.cjs.map
|
|
@@ -1 +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,
|
|
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 panAble: 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 controls: []\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,QAAS,GACT,UAAW,GACX,MAAO,EACP,SAAU,OACV,SAAU,OACV,QAAS,GACT,QAAS,EACT,WAAY,EACZ,gBAAiB,GACjB,SAAU,EACZ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"childrenWithPosition.cjs","sources":["../../../src/utils/childrenWithPosition.ts"],"sourcesContent":["import { cloneElement, isValidElement, type CSSProperties } from 'react'\n\nexport const childrenWithPosition = ({\n children,\n position,\n}: {\n children: React.ReactNode\n position: CSSProperties\n}) => {\n return isValidElement(children)\n ? cloneElement(children, {\n ...(children.props as any),\n style: Object.assign({}, position, children.props.style),\n } as any)\n : null\n}\n"],"names":["childrenWithPosition","children","position","isValidElement","cloneElement"],"mappings":"oCAEa,MAAAA,EAAuB,CAAC,CACnC,SAAAC,EACA,SAAAC,CACF,IAISC,iBAAeF,CAAQ,EAC1BG,EAAAA,aAAaH,EAAU,CACrB,GAAIA,EAAS,MACb,MAAO,OAAO,OAAO,CAAA,EAAIC,EAAUD,EAAS,MAAM,KAAK,CACzD,CAAQ,EACR"}
|
|
@@ -1,2 +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=
|
|
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=o=>({width:o.width,height:o.height}),L=F(({src:o,onLoad:w,onScaling:Z,scaleToFit:u,scaleToCover:g,...l},p)=>{const a=R(null),n=q(),{width:S,height:b}=y(E),d=A(c=>{const{canvas:e,manualZoom:t=1,defaultCentered:m}=n.getState();if(!a.current)return;if(!e){console.warn("updateViewport: !canvas");return}if(!e.backgroundImage){console.warn("updateViewport: !canvas.backgroundImage");return}const s=c.scaleToFit?h.findScaleToFit(a.current,e):c.scaleToCover?h.findScaleToCover(a.current,e):1,r=s*t;e.setViewportTransform([r,0,0,r,0,0]);let i=0,f=0;if(m&&e.backgroundImage){const I=e.backgroundImage.width||0,k=e.backgroundImage.height||0;i=(e.width-I*r)/2,f=(e.height-k*r)/2}const T=[r,0,0,r,i,f];e.setViewportTransform(T),e.requestRenderAll(),n.setState({fitZoom:s,manualZoom:t,zoom:r})},[n]);return v(()=>{d({scaleToFit:u,scaleToCover:g})},[S,b,u,g,d,n]),v(()=>{if(!o){console.warn("ReactFabricBackgroundImage: !src");return}const{domNode:c,setLoading:e}=n.getState();return e(!0),C.fromURL(o,{crossOrigin:"anonymous"}).then(t=>{const m=t.getSrc(),s=a.current?.getSrc();if(s&&m!==s)return;const{canvas:r}=n.getState();if(r){const i={...l,angle:0};if(t.set({...i,objectCaching:!1}),r.getContext().imageSmoothingEnabled=!0,r.getContext().imageSmoothingQuality="high",r.backgroundImage=t,a.current=t,requestAnimationFrame(()=>{d({scaleToFit:u,scaleToCover:g})}),!r.viewportTransform){console.warn("!viewport");return}w?.(t)}else console.warn("ReactFabric:BackgroundImage: !canvas",r)}).catch(console.error).finally(()=>{c&&(c.dataset.src=o),e(!1)}),()=>{const{canvas:t}=n.getState();t?.backgroundImage&&(t.backgroundImage=void 0,t.remove(a.current),a.current=null,t.renderAll())}},[o]),j(()=>{const{canvas:c}=n.getState();a.current&&(Object.entries(l).forEach(([e,t])=>{e==="angle"?a.current?.rotate(t):a.current?.set(e,t)}),c?.requestRenderAll())},[l,n]),V(p,()=>({instance:a.current})),null});var O=x(L);export{O as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +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
|
|
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 currentSrc = imageSource.getSrc()\n const latestSrc = backgroundImageRef.current?.getSrc()\n\n if (latestSrc && currentSrc !== latestSrc) {\n return\n }\n\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 }, [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","currentSrc","latestSrc","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsxs as
|
|
1
|
+
"use client";import{jsxs as y,jsx as h}from"react/jsx-runtime";import{Canvas as z,Point as w}from"fabric";import{useRef as c,useLayoutEffect as M,useEffect as i}from"react";import _ from"../../hooks/useDraggable.mjs";import g from"../../hooks/useResizeHandler.mjs";import{useSplitProps as A}from"../../hooks/useSplitProps.mjs";import{useStoreApi as D,useStore as E}from"../../hooks/useStore.mjs";import{bindEvents as j}from"../../utils/events.mjs";const C={position:"absolute",width:"100%",height:"100%",top:0,left:0},L=({children:S,onMouseWheel:l,...b})=>{const e=c(),s=D(),u=c(null);_();const m=c(null),N=E(t=>t.controls),[P,n]=A(b);return M(()=>{const t=u.current;e.current=new z(t||void 0,{...n});const r=j(e.current,P);return s.setState({canvas:e.current}),window.canvas=e.current,()=>{r(),e.current?.dispose(),t?.remove(),e.current=void 0,s.setState({canvas:null})}},[]),g(),i(()=>{const t=r=>{const{zoomable:Y,panAble:Z,maxManualZoom:f,minManualZoom:d,fitZoom:p=1,zoom:x}=s.getState();if(r.e.preventDefault(),r.e.stopPropagation(),r.e.wheelDeltaY!==0){if(r.e.ctrlKey||r.e.wheelDeltaY===void 0){if(!Y)return;const a=r.e.deltaY>0?.95:1.05;let o=x/p*a;o>f&&(o=f),o<d&&(o=d);const v=o*p;e.current?.zoomToPoint(new w(r.e.offsetX,r.e.offsetY),v),s.setState({manualZoom:o,zoom:v})}else{if(!Z)return;const a=1.5,o=new w(-r.e.deltaX*a,-r.e.deltaY*a);e.current?.relativePan(o)}l?.(r)}};return e.current?.on("mouse:wheel",t),()=>{e.current?.off("mouse:wheel",t)}},[l,s]),i(()=>{s.setState({domNode:m.current?.closest(".react-fabric")})},[s]),i(()=>{e.current&&(e.current.set(n),e.current.requestRenderAll())},[n]),y("div",{className:"react-fabric__canvas",ref:m,style:C,children:[h("canvas",{ref:u}),S,N.map(t=>h("div",{id:t.id,style:{position:"absolute"},className:`react-fabric__control ${t.className}`,ref:t.ref,children:t.children},t.id))]})};export{L as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +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
|
|
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 { useStore, 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 const controls = useStore(state => state.controls)\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 }, [])\n\n useResizeHandler()\n\n useEffect(() => {\n const onMouseWheelHandler = (opt: TPointerEventInfo<WheelEvent>) => {\n const { zoomable, panAble, 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 const 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 if (!panAble) return\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 {controls.map(control => (\n <div\n key={control.id}\n id={control.id}\n style={{\n position: 'absolute',\n }}\n className={`react-fabric__control ${control.className}`}\n ref={control.ref}\n >\n {control.children}\n </div>\n ))}\n </div>\n )\n}\n\nexport default Canvas\n"],"names":["style","Canvas","children","onMouseWheel","props","canvasRef","useRef","store","useStoreApi","canvasDomRef","useDraggable","domRef","controls","useStore","state","listeners","attributes","useSplitProps","useLayoutEffect","canvas","BaseCanvas","unbindEvents","bindEvents","useResizeHandler","useEffect","onMouseWheelHandler","opt","zoomable","panAble","maxManualZoom","minManualZoom","fitZoom","zoom","zoomFactor","newManualZoom","combinedZoom","Point","sensitivityFactor","delta","jsxs","jsx","control"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{jsx as O,Fragment as P}from"react/jsx-runtime";import{computePosition as A,offset as D,flip as F,shift as L}from"@floating-ui/core";import{util as b}from"fabric";import p,{useRef as C,useState as j,useCallback as v,useMemo as k,useEffect as l}from"react";import{useStore as q,useStoreApi as B}from"../../hooks/useStore.mjs";const M=()=>Math.random().toString(36).substring(2)+Date.now().toString(36),T=p.forwardRef(({children:s,className:g,placement:w="bottom",open:a=!0,onOpenChange:S,closeOnOutsideClick:x=!0,Content:h},m)=>{const f=C(void 0),n=q(e=>e.canvas),r=C(null),[u,V]=j(M()),o=B(),y=v(e=>{e!==f.current&&(f.current=e,typeof m=="function"?m(e):m&&(m.current=e))},[m]),R=k(()=>p.Children.only(s)&&p.isValidElement(s)?p.cloneElement(s,{ref:y,...s.props}):s,[s,y]),c=v(()=>{if(!f.current||!r.current||!n)return;const e=r.current.getBoundingClientRect();if(e.width===0||e.height===0){requestAnimationFrame(c);return}const t=f.current.getCoords().map(i=>b.sendPointToPlane(i,n.viewportTransform,void 0)),d={getElementRects:i=>i,getDimensions:i=>i,getClippingRect:()=>({x:0,y:0,width:n.width,height:n.height})},E={x:t[0].x,y:t[0].y,width:t[2].x-t[0].x,height:t[2].y-t[0].y};A(E,r.current.getBoundingClientRect(),{platform:d,placement:w,middleware:[D(5),F(),L({padding:5})]}).then(({x:i,y:N})=>{r.current&&Object.assign(r.current.style,{left:`${i}px`,top:`${N}px`})})},[n,w]);return l(()=>{a&&requestAnimationFrame(c)},[a,c]),l(()=>(n?.on("after:render",c),()=>{n?.off("after:render",c)}),[n,c]),l(()=>{const e=d=>{d.e.stopPropagation(),d.e.preventDefault()},t=d=>{r.current?.contains(d.target)||x&&a&&S?.(!1)};return n?.on("mouse:down",e),document.addEventListener("mousedown",t,!1),()=>{n?.off("mouse:down",e),document.removeEventListener("mousedown",t,!1)}},[n,x,S,a]),l(()=>{const{controls:e}=o.getState();if(!e.find(t=>t.id===u))return o.setState({controls:[...e,{id:u,className:g,children:h,ref:r}]}),()=>{o.setState({controls:e.filter(t=>t.id!==u)})}},[o]),l(()=>{const{controls:e}=o.getState();e.find(t=>t.id===u)&&o.setState({controls:e.map(t=>t.id===u?{...t,children:a?h:null,className:g}:t)})},[h,g,u,o,a]),O(P,{children:R})});export{T as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Control2/index.tsx"],"sourcesContent":["import { computePosition, flip, offset, shift } from '@floating-ui/core'\nimport type { ComputePositionConfig } from '@floating-ui/react'\nimport type { FabricObject, FabricObjectProps, TPointerEvent, TPointerEventInfo } from 'fabric'\nimport { util } from 'fabric'\nimport type { ReactNode } from 'react'\nimport { useState } from 'react'\nimport { useMemo } from 'react'\nimport { useCallback } from 'react'\nimport { useRef } from 'react'\nimport { useEffect } from 'react'\nimport React from 'react'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\n\n// 生成随机ID的函数\nconst generateRandomId = (): string => {\n return Math.random().toString(36).substring(2) + Date.now().toString(36)\n}\n\n/**\n * @desc 不能内置支持 selected , 因为需要 rect 开启 lockMovementX lockMovementY, 这样支持的场景就受限了\n */\nexport type Control2Props = 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 }: Control2Props,\n forwardRef,\n ) => {\n const instanceRef = useRef<FabricObject | undefined>(undefined)\n const canvas = useStore(state => state.canvas)\n const floatingElRef = useRef<HTMLDivElement>(null)\n const [id, _setId] = useState(generateRandomId())\n\n const store = useStoreApi()\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 // 这里测试下来是多余的,可删除;after:render 后都有值\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 // 这里测试下来是多余的,可删除;\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 useEffect(() => {\n const { controls } = store.getState()\n\n const control = controls.find(control => control.id === id)\n\n if (control) {\n return\n }\n\n store.setState({\n controls: [\n ...controls,\n {\n id,\n className,\n children: Content,\n ref: floatingElRef,\n },\n ],\n })\n return () => {\n store.setState({\n controls: controls.filter(control => control.id !== id),\n })\n }\n }, [store])\n\n useEffect(() => {\n const { controls } = store.getState()\n const control = controls.find(control => control.id === id)\n\n if (control) {\n store.setState({\n controls: controls.map(control =>\n control.id === id ? { ...control, children: open ? Content : null, className } : control,\n ),\n })\n }\n }, [Content, className, id, store, open])\n\n return <>{newChildren}</>\n },\n)\n\nexport default Control\n"],"names":["generateRandomId","Control","React","children","className","placement","open","onOpenChange","closeOnOutsideClick","Content","forwardRef","instanceRef","useRef","canvas","useStore","state","floatingElRef","id","_setId","useState","store","useStoreApi","refCallback","useCallback","node","newChildren","useMemo","updatePosition","floatingRect","viewportCoords","point","util","platform","data","element","virtualEl","computePosition","offset","flip","shift","x","y","useEffect","handleCanvasClick","e","handleDocumentClick","controls","control","jsx","Fragment"],"mappings":"wVAeMA,MAAAA,EAAmB,IAChB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,EAAI,KAAK,IAAI,EAAE,SAAS,EAAE,EAgBnEC,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,EAC3C,CAACK,EAAIC,CAAM,EAAIC,EAASnB,EAAkB,CAAA,EAE1CoB,EAAQC,EAAY,EAEpBC,EAAcC,EACjBC,GAAc,CAETA,IAASb,EAAY,UACvBA,EAAY,QAAUa,EAGlB,OAAOd,GAAe,WACxBA,EAAWc,CAAI,EACNd,IACTA,EAAW,QAAUc,GAG3B,EACA,CAACd,CAAU,CACb,EAGMe,EAAcC,EAAQ,IACtBxB,EAAM,SAAS,KAAKC,CAAQ,GAAKD,EAAM,eAAeC,CAAQ,EACzDD,EAAM,aAAaC,EAAU,CAClC,IAAKmB,EACL,GAAGnB,EAAS,KACd,CAAC,EAEIA,EACN,CAACA,EAAUmB,CAAW,CAAC,EAEpBK,EAAiBJ,EAAY,IAAM,CAEvC,GAAI,CAACZ,EAAY,SAAW,CAACK,EAAc,SAAW,CAACH,EACrD,OAIF,MAAMe,EAAeZ,EAAc,QAAQ,sBAC3C,EAAA,GAAIY,EAAa,QAAU,GAAKA,EAAa,SAAW,EAAG,CAEzD,sBAAsBD,CAAc,EACpC,MACF,CAGA,MAAME,EADclB,EAAY,QAAQ,UAAU,EACf,IAAImB,GAASC,EAAK,iBAAiBD,EAAOjB,EAAO,kBAAmB,MAAS,CAAC,EAE3GmB,EAAW,CACf,gBAAkBC,GAAcA,EAChC,cAAgBC,GAAiBA,EACjC,gBAAiB,KAAO,CACtB,EAAG,EACH,EAAG,EACH,MAAOrB,EAAO,MACd,OAAQA,EAAO,MACjB,EACF,EAEMsB,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,EAAWnB,EAAc,QAAQ,sBAAsB,EAAG,CACxE,SAAAgB,EACA,UAAA3B,EACA,WAAY,CAACgC,EAAO,CAAC,EAAGC,EAAK,EAAGC,EAAM,CAAE,QAAS,CAAE,CAAC,CAAC,CACvD,CAAC,EAAE,KAAK,CAAC,CAAE,EAAAC,EAAG,EAAAC,CAAE,IAAM,CACfzB,EAAc,SAEnB,OAAO,OAAOA,EAAc,QAAQ,MAAO,CACzC,KAAM,GAAGwB,CAAC,KACV,IAAK,GAAGC,CAAC,IACX,CAAC,CACH,CAAC,CACH,EAAG,CAAC5B,EAAQR,CAAS,CAAC,EAItB,OAAAqC,EAAU,IAAM,CACVpC,GACF,sBAAsBqB,CAAc,CAExC,EAAG,CAACrB,EAAMqB,CAAc,CAAC,EAEzBe,EAAU,KACR7B,GAAQ,GAAG,eAAgBc,CAAc,EAElC,IAAM,CACXd,GAAQ,IAAI,eAAgBc,CAAc,CAC5C,GACC,CAACd,EAAQc,CAAc,CAAC,EAE3Be,EAAU,IAAM,CACd,MAAMC,EAAqBC,GAAwC,CAEjEA,EAAE,EAAE,kBACJA,EAAE,EAAE,gBAUN,EAEMC,EAAuBD,GAAkB,CAEzC5B,EAAc,SAAS,SAAS4B,EAAE,MAAc,GAIhDpC,GAAuBF,GACzBC,IAAe,EAAK,CAExB,EAEA,OAAAM,GAAQ,GAAG,aAAc8B,CAAiB,EAE1C,SAAS,iBAAiB,YAAaE,EAAqB,EAAK,EAE1D,IAAM,CACXhC,GAAQ,IAAI,aAAc8B,CAAiB,EAC3C,SAAS,oBAAoB,YAAaE,EAAqB,EAAK,CACtE,CACF,EAAG,CAAChC,EAAQL,EAAqBD,EAAcD,CAAI,CAAC,EAEpDoC,EAAU,IAAM,CACd,KAAM,CAAE,SAAAI,CAAS,EAAI1B,EAAM,SAAS,EAIpC,GAFgB,CAAA0B,EAAS,KAAKC,GAAWA,EAAQ,KAAO9B,CAAE,EAM1D,OAAAG,EAAM,SAAS,CACb,SAAU,CACR,GAAG0B,EACH,CACE,GAAA7B,EACA,UAAAb,EACA,SAAUK,EACV,IAAKO,CACP,CACF,CACF,CAAC,EACM,IAAM,CACXI,EAAM,SAAS,CACb,SAAU0B,EAAS,OAAOC,GAAWA,EAAQ,KAAO9B,CAAE,CACxD,CAAC,CACH,CACF,EAAG,CAACG,CAAK,CAAC,EAEVsB,EAAU,IAAM,CACd,KAAM,CAAE,SAAAI,CAAS,EAAI1B,EAAM,SACX0B,EAAAA,EAAS,KAAKC,GAAWA,EAAQ,KAAO9B,CAAE,GAGxDG,EAAM,SAAS,CACb,SAAU0B,EAAS,IAAIC,GACrBA,EAAQ,KAAO9B,EAAK,CAAE,GAAG8B,EAAS,SAAUzC,EAAOG,EAAU,KAAM,UAAAL,CAAU,EAAI2C,CACnF,CACF,CAAC,CAEL,EAAG,CAACtC,EAASL,EAAWa,EAAIG,EAAOd,CAAI,CAAC,EAEjC0C,EAAAC,EAAA,CAAG,SAAAxB,CAAAA,CAAY,CACxB,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{Ellipse as u}from"fabric";import{forwardRef as n,useImperativeHandle as a,memo as l}from"react";import{useCreateObject as f}from"../../hooks/useCreateObject.mjs";import{useSplitProps as c}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as d}from"../../hooks/useInstancePosition.mjs";const b=n(({group:r,children:t,...o},s)=>{const[i,m,p]=c(o),e=f({Constructor:u,defaultValues:p,attributes:m,group:r,listeners:i});return a(s,()=>e,[e]),d(e,t)});var g=l(b);export{g as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +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 {
|
|
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, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type EllipseProps<T = unknown> = Partial<BaseEllipse & AllObjectEvents> & {\n group?: BaseGroup\n defaultLeft?: number\n defaultTop?: number\n defaultWidth?: number\n defaultHeight?: number\n children?: ReactNode\n} & T\n\nconst Ellipse = forwardRef<BaseEllipse | undefined, EllipseProps>(({ group, children, ...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 useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(Ellipse)\n"],"names":["Ellipse","forwardRef","group","children","props","ref","listeners","attributes","defaultValues","useSplitProps","instance","useCreateObject","BaseEllipse","useImperativeHandle","useInstancePosition","memo"],"mappings":"8TAiBA,MAAMA,EAAUC,EAAkD,CAAC,CAAE,MAAAC,EAAO,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACxG,KAAM,CAACC,EAAWC,EAAYC,CAAa,EAAIC,EAAcL,CAAK,EAE5DM,EAAWC,EAAgB,CAC/B,YAAaC,EACb,cAAAJ,EACA,WAAAD,EACA,MAAAL,EACA,UAAAI,CACF,CAAC,EACD,OAAAO,EAAoBR,EAAK,IAAMK,EAAU,CAACA,CAAQ,CAAC,EAE5CI,EAAoBJ,EAAUP,CAAQ,CAC/C,CAAC,EAED,MAAeY,EAAKf,CAAO"}
|
|
@@ -1 +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
|
|
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 }, [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,CACF,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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{IText as r,Point as p,util as u}from"fabric";import{forwardRef as f,useImperativeHandle as d,memo as c}from"react";import{useCreateObject as h}from"../../hooks/useCreateObject.mjs";import{useSplitProps as l}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as g}from"../../hooks/useInstancePosition.mjs";r.prototype.set({_getNonTransformedDimensions(){return new p(this.width,this.height).scalarAdd(this.padding)},_calculateCurrentDimensions(){return u.transformPoint(this._getTransformedDimensions(),this.getViewportTransform(),!0)}});const w=f(({group:e,text:o,children:s,...i},n)=>{const[a,m]=l(i),t=h({Constructor:r,param:o,attributes:m,group:e,listeners:a});return d(n,()=>t,[t]),g(t,s)});var x=c(w);export{x as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport {
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ITextProps<T = unknown> = Partial<ConstructorParameters<typeof IText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nIText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst ITextBox = forwardRef<IText | undefined, ITextProps>(({ group, text, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: IText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(ITextBox)\n"],"names":["IText","Point","util","ITextBox","forwardRef","group","text","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","memo"],"mappings":"iVAcAA,EAAM,UAAU,IAAI,CAClB,8BAA+B,CAE7B,OAAO,IAAIC,EAAM,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAK,eAAe,KAAK,4BAA6B,KAAK,uBAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAWC,EAA0C,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvG,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAad,EACb,MAAOM,EACP,WAAAK,EACA,MAAAN,EACA,UAAAK,CACF,CAAC,EAED,OAAAK,EAAoBN,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CG,EAAoBH,EAAUN,CAAQ,CAC/C,CAAC,EAED,IAAA,EAAeU,EAAKd,CAAQ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{FabricImage as l}from"fabric";import{forwardRef as v,useRef as t,useEffect as p,useImperativeHandle as I,memo as R}from"react";import{useStoreApi as h}from"../../hooks/useStore.mjs";import{useInstancePosition as x}from"../../hooks/useInstancePosition.mjs";const E=v(({group:n,src:o,onLoad:c,children:d,...u},g)=>{const e=t(),s=t(c),m=h(),i=t(u);return p(()=>{s.current=c,i.current=u}),p(()=>{const{canvas:a}=m.getState();if(!a?.getElement())return;const f=n??a;return l.fromURL(o,{crossOrigin:"anonymous"}).then(r=>{e.current=r,r.set(i.current),s.current?.(r),f.add(r)}),()=>{e.current&&f?.remove(e.current)}},[o,m,n]),I(g,()=>e.current),x(e.current,d)});var F=R(E);export{F as default};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Image/index.tsx"],"sourcesContent":["import type { ImageProps as FabricImageProps, ObjectEvents, SerializedImageProps } from 'fabric'\nimport { FabricImage } from 'fabric'\nimport type { Group as BaseGroup } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle, useRef, type ReactNode } from 'react'\nimport { useStoreApi } from '../../hooks/useStore'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ImageProps = Partial<FabricImageProps> & {\n src: string\n group?: BaseGroup\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n children?: ReactNode\n}\n\nconst Image = forwardRef<FabricImage | undefined, ImageProps>(({ group, src, onLoad, children, ...options }, ref) => {\n const instanceRef = useRef<FabricImage>()\n const onLoadRef = useRef(onLoad)\n const store = useStoreApi()\n const optionsRef = useRef(options)\n\n // 更新 onLoadRef\n useEffect(() => {\n onLoadRef.current = onLoad\n optionsRef.current = options\n })\n\n // 只在 src 改变时初始化 image\n useEffect(() => {\n const { canvas } = store.getState()\n if (!canvas?.getElement()) return\n\n const parent = group ?? canvas\n\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' }).then(imageSource => {\n instanceRef.current = imageSource\n imageSource.set(optionsRef.current)\n onLoadRef.current?.(imageSource)\n parent.add(imageSource)\n })\n\n return () => {\n if (instanceRef.current) {\n parent?.remove(instanceRef.current)\n }\n }\n }, [src, store, group]) // 只包含初始化需要的依赖\n\n useImperativeHandle(ref, () => instanceRef.current)\n\n return useInstancePosition(instanceRef.current, children)\n})\n\nexport default memo(Image)\n"],"names":["Image","forwardRef","group","src","onLoad","children","options","ref","instanceRef","useRef","onLoadRef","store","useStoreApi","optionsRef","useEffect","canvas","parent","FabricImage","imageSource","useImperativeHandle","useInstancePosition","memo"],"mappings":"oRAcA,MAAMA,EAAQC,EAAgD,CAAC,CAAE,MAAAC,EAAO,IAAAC,EAAK,OAAAC,EAAQ,SAAAC,EAAU,GAAGC,CAAQ,EAAGC,IAAQ,CACnH,MAAMC,EAAcC,EAAoB,EAClCC,EAAYD,EAAOL,CAAM,EACzBO,EAAQC,EAAY,EACpBC,EAAaJ,EAAOH,CAAO,EAGjC,OAAAQ,EAAU,IAAM,CACdJ,EAAU,QAAUN,EACpBS,EAAW,QAAUP,CACvB,CAAC,EAGDQ,EAAU,IAAM,CACd,KAAM,CAAE,OAAAC,CAAO,EAAIJ,EAAM,SAAS,EAClC,GAAI,CAACI,GAAQ,WAAW,EAAG,OAE3B,MAAMC,EAASd,GAASa,EAExB,OAAAE,EAAY,QAAQd,EAAK,CAAE,YAAa,WAAY,CAAC,EAAE,KAAKe,GAAe,CACzEV,EAAY,QAAUU,EACtBA,EAAY,IAAIL,EAAW,OAAO,EAClCH,EAAU,UAAUQ,CAAW,EAC/BF,EAAO,IAAIE,CAAW,CACxB,CAAC,EAEM,IAAM,CACPV,EAAY,SACdQ,GAAQ,OAAOR,EAAY,OAAO,CAEtC,CACF,EAAG,CAACL,EAAKQ,EAAOT,CAAK,CAAC,EAEtBiB,EAAoBZ,EAAK,IAAMC,EAAY,OAAO,EAE3CY,EAAoBZ,EAAY,QAASH,CAAQ,CAC1D,CAAC,EAED,IAAegB,EAAAA,EAAKrB,CAAK"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{Line as c}from"fabric";import{forwardRef as f,useImperativeHandle as l,memo as d}from"react";import{useCreateObject as x}from"../../hooks/useCreateObject.mjs";import{useSplitProps as P}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as b}from"../../hooks/useInstancePosition.mjs";const g=f(({group:e,x1:t,y1:o,x2:m,y2:s,children:i,...n},p)=>{const[a,u]=P(n),r=x({Constructor:c,param:[t,o,m,s],attributes:u,group:e,listeners:a});return l(p,()=>r,[r]),b(r,i)});var v=d(g);export{v as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +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 {
|
|
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, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type Handle = BaseLine | undefined\n\nexport type LineProps<T = unknown> = Partial<ConstructorParameters<typeof BaseLine>[1] & AllObjectEvents> & {\n group?: BaseGroup\n path?: string\n children?: ReactNode\n} & T\n\nconst Line = forwardRef<Handle, LineProps>(({ group, x1, y1, x2, y2, children, ...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 useInstancePosition(instance, children)\n})\n\nexport default memo(Line)\n"],"names":["Line","forwardRef","group","x1","y1","x2","y2","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","BaseLine","useImperativeHandle","useInstancePosition","memo"],"mappings":"2TAgBA,MAAMA,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACjG,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAaC,EACb,MAAO,CAACZ,EAAIC,EAAIC,EAAIC,CAAE,EACtB,WAAAK,EACA,MAAAT,EACA,UAAAQ,CACF,CAAC,EAED,OAAAM,EAAoBP,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CI,EAAoBJ,EAAUN,CAAQ,CAC/C,CAAC,EAED,IAAeW,EAAAA,EAAKlB,CAAI"}
|