@visactor/vrender-core 0.22.0-vstory.1 → 0.22.0-vstory.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/cjs/core/global.d.ts +0 -3
  2. package/cjs/core/global.js +1 -7
  3. package/cjs/core/global.js.map +1 -1
  4. package/cjs/graphic/config.js +1 -0
  5. package/cjs/graphic/config.js.map +1 -1
  6. package/cjs/graphic/graphic.d.ts +1 -1
  7. package/cjs/graphic/graphic.js +5 -5
  8. package/cjs/graphic/graphic.js.map +1 -1
  9. package/cjs/graphic/richtext/line.js +3 -1
  10. package/cjs/graphic/richtext/line.js.map +1 -1
  11. package/cjs/graphic/richtext/paragraph.d.ts +2 -1
  12. package/cjs/graphic/richtext/paragraph.js +61 -10
  13. package/cjs/graphic/richtext/paragraph.js.map +1 -1
  14. package/cjs/graphic/richtext.js +4 -1
  15. package/cjs/graphic/richtext.js.map +1 -1
  16. package/cjs/interface/global.d.ts +0 -1
  17. package/cjs/interface/global.js.map +1 -1
  18. package/cjs/interface/graphic/richText.d.ts +10 -0
  19. package/cjs/interface/graphic/richText.js.map +1 -1
  20. package/cjs/interface/graphic.d.ts +1 -1
  21. package/cjs/interface/graphic.js.map +1 -1
  22. package/cjs/plugins/builtin-plugin/edit-module.d.ts +2 -1
  23. package/cjs/plugins/builtin-plugin/edit-module.js +18 -13
  24. package/cjs/plugins/builtin-plugin/edit-module.js.map +1 -1
  25. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.d.ts +30 -6
  26. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js +248 -74
  27. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  28. package/cjs/render/contributions/render/contributions/image-contribution-render.d.ts +1 -1
  29. package/cjs/render/contributions/render/contributions/image-contribution-render.js +2 -2
  30. package/cjs/render/contributions/render/contributions/image-contribution-render.js.map +1 -1
  31. package/cjs/render/contributions/render/draw-contribution.js +2 -1
  32. package/cjs/render/contributions/render/draw-contribution.js.map +1 -1
  33. package/cjs/render/contributions/render/image-render.js.map +1 -1
  34. package/cjs/resource-loader/loader.js +1 -1
  35. package/cjs/resource-loader/loader.js.map +1 -1
  36. package/dist/index.es.js +439 -91
  37. package/es/core/global.d.ts +0 -3
  38. package/es/core/global.js +1 -8
  39. package/es/core/global.js.map +1 -1
  40. package/es/graphic/config.js +1 -0
  41. package/es/graphic/config.js.map +1 -1
  42. package/es/graphic/graphic.d.ts +1 -1
  43. package/es/graphic/graphic.js +5 -5
  44. package/es/graphic/graphic.js.map +1 -1
  45. package/es/graphic/richtext/line.js +3 -1
  46. package/es/graphic/richtext/line.js.map +1 -1
  47. package/es/graphic/richtext/paragraph.d.ts +2 -1
  48. package/es/graphic/richtext/paragraph.js +61 -10
  49. package/es/graphic/richtext/paragraph.js.map +1 -1
  50. package/es/graphic/richtext.js +4 -1
  51. package/es/graphic/richtext.js.map +1 -1
  52. package/es/interface/global.d.ts +0 -1
  53. package/es/interface/global.js.map +1 -1
  54. package/es/interface/graphic/richText.d.ts +10 -0
  55. package/es/interface/graphic/richText.js.map +1 -1
  56. package/es/interface/graphic.d.ts +1 -1
  57. package/es/interface/graphic.js.map +1 -1
  58. package/es/plugins/builtin-plugin/edit-module.d.ts +2 -1
  59. package/es/plugins/builtin-plugin/edit-module.js +15 -11
  60. package/es/plugins/builtin-plugin/edit-module.js.map +1 -1
  61. package/es/plugins/builtin-plugin/richtext-edit-plugin.d.ts +30 -6
  62. package/es/plugins/builtin-plugin/richtext-edit-plugin.js +248 -73
  63. package/es/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  64. package/es/render/contributions/render/contributions/image-contribution-render.d.ts +1 -1
  65. package/es/render/contributions/render/contributions/image-contribution-render.js +2 -2
  66. package/es/render/contributions/render/contributions/image-contribution-render.js.map +1 -1
  67. package/es/render/contributions/render/draw-contribution.js +1 -1
  68. package/es/render/contributions/render/draw-contribution.js.map +1 -1
  69. package/es/render/contributions/render/image-render.js.map +1 -1
  70. package/es/resource-loader/loader.js +1 -1
  71. package/es/resource-loader/loader.js.map +1 -1
  72. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/interface/graphic.ts"],"names":[],"mappings":"","file":"graphic.js","sourcesContent":["import type { IAABBBounds, IMatrix, IPointLike, IPoint, BoundsAnchorType, IOBBBounds } from '@visactor/vutils';\nimport type { IAnimate, IStep, EasingType, IAnimateTarget, ITimeline } from './animate';\nimport type { IColor } from './color';\nimport type { IGroup } from './graphic/group';\nimport type { IShadowRoot } from './graphic/shadow-root';\nimport type { ILayer } from './layer';\nimport type { INode } from './node-tree';\nimport type { ICustomPath2D } from './path';\nimport type { IStage } from './stage';\nimport type { IGlyphGraphicAttribute } from './graphic/glyph';\nimport type { IContainPointMode } from '../common/enums';\nimport type { IFace3d } from './graphic/face3d';\nimport type { IPickerService } from './picker';\n\ntype IStrokeSeg = {\n start: number; // 百分比\n // end和length二选一\n end: number; // 百分比\n length: number; // 像素长度\n};\n\n// TODO 最后加一个any\nexport type GraphicType =\n | 'area'\n | 'circle'\n | 'ellipse'\n | 'line'\n | 'rect'\n | 'rect3d'\n | 'path'\n | 'richtext'\n | 'text'\n | 'arc'\n | 'arc3d'\n | 'image'\n | 'symbol'\n | 'group'\n | 'shadowroot'\n | 'polygon'\n | 'pyramid3d'\n | 'glyph'\n | string;\n\n// Cursor style\n// See: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\nexport type Cursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out';\n\nexport type ITransform = {\n x: number;\n y: number;\n z: number;\n dx: number;\n dy: number;\n dz: number;\n scrollX: number;\n scrollY: number;\n scaleX: number;\n scaleY: number;\n scaleZ: number;\n angle: number;\n alpha: number;\n beta: number;\n scaleCenter: [number | string, number | string];\n anchor: [number | string, number | string]; // 基于AABB的锚点位置,用于简单的定位某些path\n anchor3d: [number | string, number | string, number] | [number | string, number | string]; // 3d的锚点位置\n postMatrix: IMatrix;\n};\n\nexport type IFillType = boolean | string | IColor;\nexport type IFillStyle = {\n fillOpacity: number;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n fill: IFillType;\n};\n\nexport type ILayout = {\n alignSelf: 'auto' | 'flex-start' | 'flex-end' | 'center';\n};\n\nexport type IBorderStyle = Omit<IStrokeStyle, 'outerBorder' | 'innerBorder'> & {\n distance: number | string;\n visible?: boolean;\n};\n\nexport type IStrokeType = boolean | string | IColor | null;\nexport type IStrokeStyle = {\n outerBorder: Partial<IBorderStyle>;\n innerBorder: Partial<IBorderStyle>;\n strokeOpacity: number;\n lineDash: number[];\n lineDashOffset: number;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n // 描边的boundsBuffer,用于控制bounds的buffer\n strokeBoundsBuffer: number;\n /**\n * stroke - true 全描边\n * stroke - false 不描边\n * stroke 为数值类型,适用于rect\\arc等图形,用于配置部分描边的场景,其中\n *\n * 0b00000 - 不描边\n * 0b000001 - top\n * 0b000010 - right\n * 0b000100 - bottom\n * 0b001000 - left\n * 相应的:\n * 0b000011 - top + right\n * 0b000111 - top + right + bottom\n * 0b001111 - 全描边\n *\n * stroke - boolean[],适用于rect\\arc等图形,用于配置部分描边的场景\n */\n stroke: IStrokeType[] | IStrokeType;\n};\n\ntype TextureType = 'circle' | 'diamond' | 'rect' | 'vertical-line' | 'horizontal-line' | 'bias-lr' | 'bias-rl' | 'grid';\n\nexport type IConnectedStyle = {\n // 连接,取零或者断开\n connectedType: 'connect' | 'zero' | 'none';\n connectedStyle: {\n stroke: IStrokeStyle['stroke'];\n strokeOpacity: IStrokeStyle['strokeOpacity'];\n lineDash: IStrokeStyle['lineDash'];\n lineDashOffset: IStrokeStyle['lineDashOffset'];\n lineCap: IStrokeStyle['lineCap'];\n lineJoin: IStrokeStyle['lineJoin'];\n lineWidth: IStrokeStyle['lineWidth'];\n fill: IFillStyle['fill'];\n fillOpacity: IFillStyle['fillOpacity'];\n };\n connectedX: number;\n connectedY: number;\n};\n\nexport type IBackgroundConfig = {\n stroke?: string | boolean;\n fill?: string | boolean;\n lineWidth?: number;\n cornerRadius?: number;\n expandX?: number;\n expandY?: number;\n};\n\ntype IBackgroundType = string | HTMLImageElement | HTMLCanvasElement | IBackgroundConfig;\n\nexport interface SimpleDomStyleOptions {\n width: number; // 容器的宽度\n height: number; // 容器的高度\n style?:\n | string\n | Record<string, any>\n | ((\n pos: { top: number; left: number; width: number; height: number },\n graphic: IGraphic,\n wrapContainer: HTMLElement\n ) => Record<string, any>); // 容器的样式\n}\n\nexport interface CommonDomOptions {\n id?: string;\n container: string | HTMLElement | null; // id或者dom\n visible?: boolean;\n pointerEvents?: boolean | string;\n // 可穿透的事件列表\n // @since 0.21.2\n penetrateEventList?: string[];\n anchorType?: 'position' | 'boundsLeftTop' | BoundsAnchorType;\n}\n\nexport type IGraphicStyle = ILayout &\n IFillStyle &\n IStrokeStyle &\n IPickStyle & {\n forceBoundsWidth: number | (() => number) | undefined;\n forceBoundsHeight: number | (() => number) | undefined;\n opacity: number;\n shadowGraphic?: IGraphic | undefined;\n backgroundMode: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'; // 填充模式(与具体图元有关)\n backgroundFit: boolean; // 是否正好填充,只在repeat-x或者repeat-y以及no-repeat的时候生效\n // 背景图缩放,只在no-repeat的时候生效\n backgroundScale: number;\n // 背景图偏移,只在no-repeat的时候生效\n backgroundOffsetX: number;\n backgroundOffsetY: number;\n backgroundClip: boolean;\n backgroundCornerRadius: number | number[];\n backgroundOpacity: number;\n // 纹理是否自动做动画\n autoAnimateTexture: boolean;\n // 如果做动画的话,这里代表ratio\n textureRatio: number;\n textureOptions: any;\n background:\n | IBackgroundType\n | {\n background: IBackgroundType;\n dx?: number;\n dy?: number;\n width?: number;\n height?: number;\n x?: number;\n y?: number;\n }\n | null; // 背景,可以与fill同时存在\n texture: TextureType | string; // 纹理\n textureColor: string; // 纹理颜色\n textureSize: number; // 纹理大小\n texturePadding: number; // 纹理间隙\n blur: number;\n filter: string;\n cursor: Cursor | null; // 鼠标样式\n renderStyle?: 'default' | 'rough' | any;\n // HTML的dom或者string\n html:\n | ({\n dom: string | HTMLElement; // dom字符串或者dom\n } & SimpleDomStyleOptions &\n CommonDomOptions)\n | null;\n react:\n | ({\n element: any; // react场景节点\n } & SimpleDomStyleOptions &\n CommonDomOptions)\n | null;\n };\n\nexport type IPickStyle = {\n // 给stroke模式的pick额外加的buffer,用于外界控制stroke区域的pick范围\n pickStrokeBuffer: number;\n};\n\nexport type IDebugType = {\n _debug_bounds: boolean | ((c: any, g: any) => void);\n};\nexport type IGraphicAttribute = IDebugType &\n IGraphicStyle &\n ITransform & {\n /**\n * stroke百分比\n */\n strokeSeg: IStrokeSeg | null;\n // 包围盒的padding\n boundsPadding: number | number[];\n /**\n * 选择模式,精确模式,粗糙模式(包围盒模式),自定义模式\n */\n pickMode: 'accurate' | 'imprecise' | 'custom';\n boundsMode: 'accurate' | 'imprecise';\n customPickShape: () => boolean | null;\n /**\n * 是否支持事件拾取,默认为 true。\n * @default true\n */\n pickable: boolean;\n /**\n * 是否支持fill拾取,默认为 true。\n * @experimental\n * @default true\n */\n fillPickable: boolean;\n /**\n * 是否支持stroke拾取,默认为 true。\n * @experimental\n * @default true\n */\n strokePickable: boolean;\n /**\n * 对于 group 节点,是否支持其子元素的事件拾取,默认为 true。\n * 如果 group `pickable` 关闭,`childrenPickable` 开启,那么 group 的子节点仍参与事件拾取\n * @default true\n */\n childrenPickable: boolean;\n /**\n * 元素是否可见。\n * @default true\n */\n visible: boolean;\n zIndex: number;\n layout: any;\n /**\n * 是否隐藏元素(只是绘制的时候不绘制)\n */\n renderable: boolean;\n /**\n * 是否在3d中控制方向\n * false: 不控制方向\n * true: 始终控制方向朝摄像机\n */\n keepDirIn3d?: boolean;\n shadowRootIdx: number;\n shadowPickMode?: 'full' | 'graphic';\n globalZIndex: number;\n globalCompositeOperation: CanvasRenderingContext2D['globalCompositeOperation'] | '';\n // 完全支持滚动 | 完全不支持滚动 | 支持x方向的滚动 | 支持y方向的滚动\n overflow: 'scroll' | 'hidden' | 'scroll-x' | 'scroll-y';\n // 绘制fill和stroke的顺序,为0表示fill先绘制,1表示stroke先绘制\n fillStrokeOrder: number;\n // @since 0.20.15\n // 保持stroke的scale,默认为false,为true的话stroke显示的宽度会随着scale变化\n keepStrokeScale: boolean;\n };\n\nexport interface IGraphicJson<T extends Partial<IGraphicAttribute> = Partial<IGraphicAttribute>> {\n attribute: Partial<T>;\n _uid: number;\n type: string;\n name: string;\n children: IGraphicJson<T>[];\n}\n\n/** the context of setAttribute */\nexport type ISetAttributeContext = {\n /** type of setAttribute */\n type?: number;\n animationState?: {\n step?: IStep;\n isFirstFrameOfStep?: boolean;\n /** ratio of animation */\n ratio?: number;\n /** is animation end? */\n end?: boolean;\n };\n skipUpdateCallback?: boolean;\n};\n\nexport type IGraphicAnimateParams = {\n slience?: boolean;\n id?: number | string;\n timeline?: ITimeline;\n onStart?: () => void;\n onFrame?: (step: IStep, ratio: number) => void;\n onEnd?: () => void;\n onRemove?: () => void;\n interpolate?: (key: string, ratio: number, from: any, to: any, nextAttributes: any) => boolean;\n};\n\nexport interface IGraphic<T extends Partial<IGraphicAttribute> = Partial<IGraphicAttribute>>\n extends INode,\n IAnimateTarget {\n type?: GraphicType;\n numberType?: number;\n stage?: IStage;\n layer?: ILayer;\n shadowRoot?: IShadowRoot;\n glyphHost?: IGraphic<IGlyphGraphicAttribute>;\n backgroundImg?: boolean;\n attachedThemeGraphic?: IGraphic<any>;\n\n bindDom?: Map<\n string | HTMLElement,\n { container: HTMLElement | string; dom: HTMLElement | any; wrapGroup: HTMLDivElement | any; root?: any }\n >;\n\n valid: boolean;\n parent: IGroup | null;\n isContainer?: boolean;\n // 是否是3d模式(是否应用3d视角)\n in3dMode?: boolean;\n\n // 上次更新的stamp\n stamp?: number;\n animationBackUps?: {\n from: Record<string, any>;\n to: Record<string, any>;\n };\n\n attribute: Partial<T>;\n\n /** 用于实现morph动画场景,转换成bezier曲线渲染 */\n pathProxy?: ICustomPath2D | ((attrs: T) => ICustomPath2D);\n incremental?: number;\n incrementalAt?: number;\n\n /** 记录state对应的图形属性 */\n states?: Record<string, Partial<T>>;\n normalAttrs?: Partial<T>;\n stateProxy?: (stateName: string, targetStates?: string[]) => Partial<T>;\n findFace?: () => IFace3d;\n toggleState: (stateName: string, hasAnimation?: boolean) => void;\n removeState: (stateName: string, hasAnimation?: boolean) => void;\n clearStates: (hasAnimation?: boolean) => void;\n useStates: (states: string[], hasAnimation?: boolean) => void;\n addState: (stateName: string, keepCurrentStates?: boolean, hasAnimation?: boolean) => void;\n hasState: (stateName?: string) => boolean;\n getState: (stateName: string) => Partial<T>;\n onBeforeAttributeUpdate?: (\n val: any,\n attributes: Partial<T>,\n key: null | string | string[],\n context?: ISetAttributeContext\n ) => T | undefined;\n applyStateAttrs: (attrs: Partial<T>, stateNames: string[], hasAnimation?: boolean, isClear?: boolean) => void;\n updateNormalAttrs: (stateAttrs: Partial<T>) => void;\n\n // get\n readonly AABBBounds: IAABBBounds; // 用于获取当前节点的AABB包围盒\n readonly OBBBounds: IOBBBounds; // 获取OBB包围盒,旋转防重叠需要用\n readonly globalAABBBounds: IAABBBounds; // 全局AABB包围盒\n readonly transMatrix: IMatrix; // 变换矩阵,动态计算\n readonly globalTransMatrix: IMatrix; // 变换矩阵,动态计算\n\n getOffsetXY: (attr?: ITransform) => IPoint;\n\n // function\n containsPoint: (x: number, y: number, mode?: IContainPointMode, picker?: IPickerService) => boolean;\n\n setMode: (mode: '3d' | '2d') => void;\n isValid: () => boolean;\n\n // TODO: transform API\n // 基于当前transform的变换,普通用户尽量别用,拿捏不住的~\n translate: (x: number, y: number) => this;\n translateTo: (x: number, y: number) => this;\n scale: (scaleX: number, scaleY: number, scaleCenter?: IPointLike) => this;\n scaleTo: (scaleX: number, scaleY: number) => this;\n rotate: (angle: number, rotateCenter?: IPointLike) => this;\n rotateTo: (angle: number) => this;\n skewTo: (b: number, c: number) => this;\n addUpdateBoundTag: () => void;\n addUpdateShapeAndBoundsTag: () => void;\n addUpdateLayoutTag: () => void;\n\n update: (d?: { bounds: boolean; trans: boolean }) => void;\n\n // animate\n animate: (params?: IGraphicAnimateParams) => IAnimate;\n\n // 语法糖,可有可无,有的为了首屏性能考虑做成get方法,有的由外界直接托管,内部不赋值\n name?: string;\n\n // 供render处理shape缓存tag\n shouldUpdateShape: () => boolean;\n clearUpdateShapeTag: () => void;\n\n // // 供render缓存shape\n // cacheShape?: ICustomPath2D;\n // // 线段使用的path2D\n // cacheLine?: ISegPath2D | ISegPath2D[];\n // // 面积图使用的path2D\n // cacheArea?: IAreaCacheItem | IAreaCacheItem[];\n\n setAttributes: (params: Partial<T>, forceUpdateTag?: boolean, context?: ISetAttributeContext) => void;\n\n initAttributes: (params: Partial<T>) => void;\n\n setAttribute: (key: string, value: any, forceUpdateTag?: boolean, context?: ISetAttributeContext) => void;\n\n setStage: (stage?: IStage, layer?: ILayer) => void;\n onSetStage: (cb: (g: IGraphic, stage: IStage) => void) => void;\n\n shouldUpdateAABBBounds: () => boolean;\n shouldSelfChangeUpdateAABBBounds: () => boolean;\n shouldUpdateGlobalMatrix: () => boolean;\n\n addUpdatePositionTag: () => void;\n addUpdateGlobalPositionTag: () => void;\n\n attachShadow: () => IShadowRoot;\n detachShadow: () => void;\n\n toJson: () => IGraphicJson;\n\n /** 创建pathProxy */\n createPathProxy: (path?: string) => void;\n /** 将图形转换成CustomPath2D */\n toCustomPath?: () => ICustomPath2D;\n\n resources?: Map<\n string | HTMLImageElement | HTMLCanvasElement | IBackgroundConfig,\n { state: 'init' | 'loading' | 'success' | 'fail'; data?: HTMLImageElement | HTMLCanvasElement }\n >;\n imageLoadSuccess: (url: string, data: HTMLImageElement) => void;\n imageLoadFail: (url: string) => void;\n\n clone: () => IGraphic;\n stopAnimates: (stopChildren?: boolean) => void;\n getNoWorkAnimateAttr: () => Record<string, number>;\n getGraphicTheme: () => T;\n}\n\nexport interface IRoot extends IGraphic {\n pick: (x: number, y: number) => IGraphic;\n}\n\n/**\n * 动画配置\n */\nexport type IAnimateConfig = {\n duration?: number;\n easing?: EasingType;\n};\n\nexport type GraphicReleaseStatus = 'released' | 'willRelease';\n"]}
1
+ {"version":3,"sources":["../src/interface/graphic.ts"],"names":[],"mappings":"","file":"graphic.js","sourcesContent":["import type { IAABBBounds, IMatrix, IPointLike, IPoint, BoundsAnchorType, IOBBBounds } from '@visactor/vutils';\nimport type { IAnimate, IStep, EasingType, IAnimateTarget, ITimeline } from './animate';\nimport type { IColor } from './color';\nimport type { IGroup } from './graphic/group';\nimport type { IShadowRoot } from './graphic/shadow-root';\nimport type { ILayer } from './layer';\nimport type { INode } from './node-tree';\nimport type { ICustomPath2D } from './path';\nimport type { IStage } from './stage';\nimport type { IGlyphGraphicAttribute } from './graphic/glyph';\nimport type { IContainPointMode } from '../common/enums';\nimport type { IFace3d } from './graphic/face3d';\nimport type { IPickerService } from './picker';\n\ntype IStrokeSeg = {\n start: number; // 百分比\n // end和length二选一\n end: number; // 百分比\n length: number; // 像素长度\n};\n\n// TODO 最后加一个any\nexport type GraphicType =\n | 'area'\n | 'circle'\n | 'ellipse'\n | 'line'\n | 'rect'\n | 'rect3d'\n | 'path'\n | 'richtext'\n | 'text'\n | 'arc'\n | 'arc3d'\n | 'image'\n | 'symbol'\n | 'group'\n | 'shadowroot'\n | 'polygon'\n | 'pyramid3d'\n | 'glyph'\n | string;\n\n// Cursor style\n// See: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor\nexport type Cursor =\n | 'auto'\n | 'default'\n | 'none'\n | 'context-menu'\n | 'help'\n | 'pointer'\n | 'progress'\n | 'wait'\n | 'cell'\n | 'crosshair'\n | 'text'\n | 'vertical-text'\n | 'alias'\n | 'copy'\n | 'move'\n | 'no-drop'\n | 'not-allowed'\n | 'grab'\n | 'grabbing'\n | 'all-scroll'\n | 'col-resize'\n | 'row-resize'\n | 'n-resize'\n | 'e-resize'\n | 's-resize'\n | 'w-resize'\n | 'ne-resize'\n | 'nw-resize'\n | 'se-resize'\n | 'sw-resize'\n | 'ew-resize'\n | 'ns-resize'\n | 'nesw-resize'\n | 'nwse-resize'\n | 'zoom-in'\n | 'zoom-out';\n\nexport type ITransform = {\n x: number;\n y: number;\n z: number;\n dx: number;\n dy: number;\n dz: number;\n scrollX: number;\n scrollY: number;\n scaleX: number;\n scaleY: number;\n scaleZ: number;\n angle: number;\n alpha: number;\n beta: number;\n scaleCenter: [number | string, number | string];\n anchor: [number | string, number | string]; // 基于AABB的锚点位置,用于简单的定位某些path\n anchor3d: [number | string, number | string, number] | [number | string, number | string]; // 3d的锚点位置\n postMatrix: IMatrix;\n};\n\nexport type IFillType = boolean | string | IColor;\nexport type IFillStyle = {\n fillOpacity: number;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n fill: IFillType;\n};\n\nexport type ILayout = {\n alignSelf: 'auto' | 'flex-start' | 'flex-end' | 'center';\n};\n\nexport type IBorderStyle = Omit<IStrokeStyle, 'outerBorder' | 'innerBorder'> & {\n distance: number | string;\n visible?: boolean;\n};\n\nexport type IStrokeType = boolean | string | IColor | null;\nexport type IStrokeStyle = {\n outerBorder: Partial<IBorderStyle>;\n innerBorder: Partial<IBorderStyle>;\n strokeOpacity: number;\n lineDash: number[];\n lineDashOffset: number;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n // 描边的boundsBuffer,用于控制bounds的buffer\n strokeBoundsBuffer: number;\n /**\n * stroke - true 全描边\n * stroke - false 不描边\n * stroke 为数值类型,适用于rect\\arc等图形,用于配置部分描边的场景,其中\n *\n * 0b00000 - 不描边\n * 0b000001 - top\n * 0b000010 - right\n * 0b000100 - bottom\n * 0b001000 - left\n * 相应的:\n * 0b000011 - top + right\n * 0b000111 - top + right + bottom\n * 0b001111 - 全描边\n *\n * stroke - boolean[],适用于rect\\arc等图形,用于配置部分描边的场景\n */\n stroke: IStrokeType[] | IStrokeType;\n};\n\ntype TextureType = 'circle' | 'diamond' | 'rect' | 'vertical-line' | 'horizontal-line' | 'bias-lr' | 'bias-rl' | 'grid';\n\nexport type IConnectedStyle = {\n // 连接,取零或者断开\n connectedType: 'connect' | 'zero' | 'none';\n connectedStyle: {\n stroke: IStrokeStyle['stroke'];\n strokeOpacity: IStrokeStyle['strokeOpacity'];\n lineDash: IStrokeStyle['lineDash'];\n lineDashOffset: IStrokeStyle['lineDashOffset'];\n lineCap: IStrokeStyle['lineCap'];\n lineJoin: IStrokeStyle['lineJoin'];\n lineWidth: IStrokeStyle['lineWidth'];\n fill: IFillStyle['fill'];\n fillOpacity: IFillStyle['fillOpacity'];\n };\n connectedX: number;\n connectedY: number;\n};\n\nexport type IBackgroundConfig = {\n stroke?: string | boolean;\n fill?: string | boolean;\n lineWidth?: number;\n cornerRadius?: number;\n expandX?: number;\n expandY?: number;\n};\n\ntype IBackgroundType = string | HTMLImageElement | HTMLCanvasElement | IBackgroundConfig;\n\nexport interface SimpleDomStyleOptions {\n width: number; // 容器的宽度\n height: number; // 容器的高度\n style?:\n | string\n | Record<string, any>\n | ((\n pos: { top: number; left: number; width: number; height: number },\n graphic: IGraphic,\n wrapContainer: HTMLElement\n ) => Record<string, any>); // 容器的样式\n}\n\nexport interface CommonDomOptions {\n id?: string;\n container: string | HTMLElement | null; // id或者dom\n visible?: boolean;\n pointerEvents?: boolean | string;\n // 可穿透的事件列表\n // @since 0.21.2\n penetrateEventList?: string[];\n anchorType?: 'position' | 'boundsLeftTop' | BoundsAnchorType;\n}\n\nexport type IGraphicStyle = ILayout &\n IFillStyle &\n IStrokeStyle &\n IPickStyle & {\n forceBoundsWidth: number | (() => number) | undefined;\n forceBoundsHeight: number | (() => number) | undefined;\n opacity: number;\n shadowGraphic?: IGraphic | undefined;\n backgroundMode: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'; // 填充模式(与具体图元有关)\n backgroundFit: boolean; // 是否正好填充,只在repeat-x或者repeat-y以及no-repeat的时候生效\n // 背景图缩放,只在no-repeat的时候生效\n backgroundScale: number;\n // 背景图偏移,只在no-repeat的时候生效\n backgroundOffsetX: number;\n backgroundOffsetY: number;\n backgroundClip: boolean;\n backgroundCornerRadius: number | number[];\n backgroundOpacity: number;\n // 纹理是否自动做动画\n autoAnimateTexture: boolean;\n // 如果做动画的话,这里代表ratio\n textureRatio: number;\n textureOptions: any;\n background:\n | IBackgroundType\n | {\n background: IBackgroundType;\n dx?: number;\n dy?: number;\n width?: number;\n height?: number;\n x?: number;\n y?: number;\n }\n | null; // 背景,可以与fill同时存在\n texture: TextureType | string; // 纹理\n textureColor: string; // 纹理颜色\n textureSize: number; // 纹理大小\n texturePadding: number; // 纹理间隙\n blur: number;\n filter: string;\n cursor: Cursor | null; // 鼠标样式\n renderStyle?: 'default' | 'rough' | any;\n // HTML的dom或者string\n html:\n | ({\n dom: string | HTMLElement; // dom字符串或者dom\n } & SimpleDomStyleOptions &\n CommonDomOptions)\n | null;\n react:\n | ({\n element: any; // react场景节点\n } & SimpleDomStyleOptions &\n CommonDomOptions)\n | null;\n };\n\nexport type IPickStyle = {\n // 给stroke模式的pick额外加的buffer,用于外界控制stroke区域的pick范围\n pickStrokeBuffer: number;\n};\n\nexport type IDebugType = {\n _debug_bounds: boolean | ((c: any, g: any) => void);\n};\nexport type IGraphicAttribute = IDebugType &\n IGraphicStyle &\n ITransform & {\n /**\n * stroke百分比\n */\n strokeSeg: IStrokeSeg | null;\n // 包围盒的padding\n boundsPadding: number | number[];\n /**\n * 选择模式,精确模式,粗糙模式(包围盒模式),自定义模式\n */\n pickMode: 'accurate' | 'imprecise' | 'custom';\n boundsMode: 'accurate' | 'imprecise' | 'empty';\n customPickShape: () => boolean | null;\n /**\n * 是否支持事件拾取,默认为 true。\n * @default true\n */\n pickable: boolean;\n /**\n * 是否支持fill拾取,默认为 true。\n * @experimental\n * @default true\n */\n fillPickable: boolean;\n /**\n * 是否支持stroke拾取,默认为 true。\n * @experimental\n * @default true\n */\n strokePickable: boolean;\n /**\n * 对于 group 节点,是否支持其子元素的事件拾取,默认为 true。\n * 如果 group `pickable` 关闭,`childrenPickable` 开启,那么 group 的子节点仍参与事件拾取\n * @default true\n */\n childrenPickable: boolean;\n /**\n * 元素是否可见。\n * @default true\n */\n visible: boolean;\n zIndex: number;\n layout: any;\n /**\n * 是否隐藏元素(只是绘制的时候不绘制)\n */\n renderable: boolean;\n /**\n * 是否在3d中控制方向\n * false: 不控制方向\n * true: 始终控制方向朝摄像机\n */\n keepDirIn3d?: boolean;\n shadowRootIdx: number;\n shadowPickMode?: 'full' | 'graphic';\n globalZIndex: number;\n globalCompositeOperation: CanvasRenderingContext2D['globalCompositeOperation'] | '';\n // 完全支持滚动 | 完全不支持滚动 | 支持x方向的滚动 | 支持y方向的滚动\n overflow: 'scroll' | 'hidden' | 'scroll-x' | 'scroll-y';\n // 绘制fill和stroke的顺序,为0表示fill先绘制,1表示stroke先绘制\n fillStrokeOrder: number;\n // @since 0.20.15\n // 保持stroke的scale,默认为false,为true的话stroke显示的宽度会随着scale变化\n keepStrokeScale: boolean;\n };\n\nexport interface IGraphicJson<T extends Partial<IGraphicAttribute> = Partial<IGraphicAttribute>> {\n attribute: Partial<T>;\n _uid: number;\n type: string;\n name: string;\n children: IGraphicJson<T>[];\n}\n\n/** the context of setAttribute */\nexport type ISetAttributeContext = {\n /** type of setAttribute */\n type?: number;\n animationState?: {\n step?: IStep;\n isFirstFrameOfStep?: boolean;\n /** ratio of animation */\n ratio?: number;\n /** is animation end? */\n end?: boolean;\n };\n skipUpdateCallback?: boolean;\n};\n\nexport type IGraphicAnimateParams = {\n slience?: boolean;\n id?: number | string;\n timeline?: ITimeline;\n onStart?: () => void;\n onFrame?: (step: IStep, ratio: number) => void;\n onEnd?: () => void;\n onRemove?: () => void;\n interpolate?: (key: string, ratio: number, from: any, to: any, nextAttributes: any) => boolean;\n};\n\nexport interface IGraphic<T extends Partial<IGraphicAttribute> = Partial<IGraphicAttribute>>\n extends INode,\n IAnimateTarget {\n type?: GraphicType;\n numberType?: number;\n stage?: IStage;\n layer?: ILayer;\n shadowRoot?: IShadowRoot;\n glyphHost?: IGraphic<IGlyphGraphicAttribute>;\n backgroundImg?: boolean;\n attachedThemeGraphic?: IGraphic<any>;\n\n bindDom?: Map<\n string | HTMLElement,\n { container: HTMLElement | string; dom: HTMLElement | any; wrapGroup: HTMLDivElement | any; root?: any }\n >;\n\n valid: boolean;\n parent: IGroup | null;\n isContainer?: boolean;\n // 是否是3d模式(是否应用3d视角)\n in3dMode?: boolean;\n\n // 上次更新的stamp\n stamp?: number;\n animationBackUps?: {\n from: Record<string, any>;\n to: Record<string, any>;\n };\n\n attribute: Partial<T>;\n\n /** 用于实现morph动画场景,转换成bezier曲线渲染 */\n pathProxy?: ICustomPath2D | ((attrs: T) => ICustomPath2D);\n incremental?: number;\n incrementalAt?: number;\n\n /** 记录state对应的图形属性 */\n states?: Record<string, Partial<T>>;\n normalAttrs?: Partial<T>;\n stateProxy?: (stateName: string, targetStates?: string[]) => Partial<T>;\n findFace?: () => IFace3d;\n toggleState: (stateName: string, hasAnimation?: boolean) => void;\n removeState: (stateName: string, hasAnimation?: boolean) => void;\n clearStates: (hasAnimation?: boolean) => void;\n useStates: (states: string[], hasAnimation?: boolean) => void;\n addState: (stateName: string, keepCurrentStates?: boolean, hasAnimation?: boolean) => void;\n hasState: (stateName?: string) => boolean;\n getState: (stateName: string) => Partial<T>;\n onBeforeAttributeUpdate?: (\n val: any,\n attributes: Partial<T>,\n key: null | string | string[],\n context?: ISetAttributeContext\n ) => T | undefined;\n applyStateAttrs: (attrs: Partial<T>, stateNames: string[], hasAnimation?: boolean, isClear?: boolean) => void;\n updateNormalAttrs: (stateAttrs: Partial<T>) => void;\n\n // get\n readonly AABBBounds: IAABBBounds; // 用于获取当前节点的AABB包围盒\n readonly OBBBounds: IOBBBounds; // 获取OBB包围盒,旋转防重叠需要用\n readonly globalAABBBounds: IAABBBounds; // 全局AABB包围盒\n readonly transMatrix: IMatrix; // 变换矩阵,动态计算\n readonly globalTransMatrix: IMatrix; // 变换矩阵,动态计算\n\n getOffsetXY: (attr?: ITransform) => IPoint;\n\n // function\n containsPoint: (x: number, y: number, mode?: IContainPointMode, picker?: IPickerService) => boolean;\n\n setMode: (mode: '3d' | '2d') => void;\n isValid: () => boolean;\n\n // TODO: transform API\n // 基于当前transform的变换,普通用户尽量别用,拿捏不住的~\n translate: (x: number, y: number) => this;\n translateTo: (x: number, y: number) => this;\n scale: (scaleX: number, scaleY: number, scaleCenter?: IPointLike) => this;\n scaleTo: (scaleX: number, scaleY: number) => this;\n rotate: (angle: number, rotateCenter?: IPointLike) => this;\n rotateTo: (angle: number) => this;\n skewTo: (b: number, c: number) => this;\n addUpdateBoundTag: () => void;\n addUpdateShapeAndBoundsTag: () => void;\n addUpdateLayoutTag: () => void;\n\n update: (d?: { bounds: boolean; trans: boolean }) => void;\n\n // animate\n animate: (params?: IGraphicAnimateParams) => IAnimate;\n\n // 语法糖,可有可无,有的为了首屏性能考虑做成get方法,有的由外界直接托管,内部不赋值\n name?: string;\n\n // 供render处理shape缓存tag\n shouldUpdateShape: () => boolean;\n clearUpdateShapeTag: () => void;\n\n // // 供render缓存shape\n // cacheShape?: ICustomPath2D;\n // // 线段使用的path2D\n // cacheLine?: ISegPath2D | ISegPath2D[];\n // // 面积图使用的path2D\n // cacheArea?: IAreaCacheItem | IAreaCacheItem[];\n\n setAttributes: (params: Partial<T>, forceUpdateTag?: boolean, context?: ISetAttributeContext) => void;\n\n initAttributes: (params: Partial<T>) => void;\n\n setAttribute: (key: string, value: any, forceUpdateTag?: boolean, context?: ISetAttributeContext) => void;\n\n setStage: (stage?: IStage, layer?: ILayer) => void;\n onSetStage: (cb: (g: IGraphic, stage: IStage) => void) => void;\n\n shouldUpdateAABBBounds: () => boolean;\n shouldSelfChangeUpdateAABBBounds: () => boolean;\n shouldUpdateGlobalMatrix: () => boolean;\n\n addUpdatePositionTag: () => void;\n addUpdateGlobalPositionTag: () => void;\n\n attachShadow: () => IShadowRoot;\n detachShadow: () => void;\n\n toJson: () => IGraphicJson;\n\n /** 创建pathProxy */\n createPathProxy: (path?: string) => void;\n /** 将图形转换成CustomPath2D */\n toCustomPath?: () => ICustomPath2D;\n\n resources?: Map<\n string | HTMLImageElement | HTMLCanvasElement | IBackgroundConfig,\n { state: 'init' | 'loading' | 'success' | 'fail'; data?: HTMLImageElement | HTMLCanvasElement }\n >;\n imageLoadSuccess: (url: string, data: HTMLImageElement) => void;\n imageLoadFail: (url: string) => void;\n\n clone: () => IGraphic;\n stopAnimates: (stopChildren?: boolean) => void;\n getNoWorkAnimateAttr: () => Record<string, number>;\n getGraphicTheme: () => T;\n}\n\nexport interface IRoot extends IGraphic {\n pick: (x: number, y: number) => IGraphic;\n}\n\n/**\n * 动画配置\n */\nexport type IAnimateConfig = {\n duration?: number;\n easing?: EasingType;\n};\n\nexport type GraphicReleaseStatus = 'released' | 'willRelease';\n"]}
@@ -1,4 +1,5 @@
1
- import type { IRichText, IRichTextCharacter } from '../../interface';
1
+ import type { IRichText, IRichTextCharacter, IRichTextGraphicAttribute } from '../../interface';
2
+ export declare function getDefaultCharacterConfig(attribute: IRichTextGraphicAttribute): any;
2
3
  export declare function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number;
3
4
  export declare function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number;
4
5
  export declare class EditModule {
@@ -10,6 +10,18 @@ var __rest = this && this.__rest || function(s, e) {
10
10
 
11
11
  import { application } from "../../application";
12
12
 
13
+ export function getDefaultCharacterConfig(attribute) {
14
+ const {fill: fill = "black", stroke: stroke = !1, fontWeight: fontWeight = "normal", fontFamily: fontFamily = "Arial"} = attribute;
15
+ let {fontSize: fontSize = 12} = attribute;
16
+ return isFinite(fontSize) || (fontSize = 12), {
17
+ fill: fill,
18
+ stroke: stroke,
19
+ fontSize: fontSize,
20
+ fontWeight: fontWeight,
21
+ fontFamily: fontFamily
22
+ };
23
+ }
24
+
13
25
  export function findConfigIndexByCursorIdx(textConfig, cursorIndex) {
14
26
  if (cursorIndex < 0) return 0;
15
27
  const intCursorIndex = Math.round(cursorIndex);
@@ -51,9 +63,7 @@ export class EditModule {
51
63
  if (this.composingConfigIdx = this.cursorIndex < 0 ? 0 : findConfigIndexByCursorIdx(textConfig, this.cursorIndex),
52
64
  this.cursorIndex < 0) {
53
65
  const config = textConfig[0];
54
- textConfig.unshift(Object.assign(Object.assign({
55
- fill: "black"
56
- }, config), {
66
+ textConfig.unshift(Object.assign(Object.assign(Object.assign({}, getDefaultCharacterConfig(this.currRt.attribute)), config), {
57
67
  text: ""
58
68
  }));
59
69
  } else {
@@ -69,21 +79,15 @@ export class EditModule {
69
79
  cb(text, this.isComposing, this.cursorIndex, this.currRt);
70
80
  }));
71
81
  }, this.handleInput = ev => {
72
- var _a, _b, _c, _d;
73
82
  if (!this.currRt) return;
74
83
  if ("historyUndo" === ev.inputType) return;
75
- const _e = this.currRt.attribute, {textConfig: textConfig = []} = _e, rest = __rest(_e, [ "textConfig" ]);
84
+ const _a = this.currRt.attribute, {textConfig: textConfig = []} = _a, rest = __rest(_a, [ "textConfig" ]);
76
85
  if ("Backspace" === ev.type && !textConfig.length) return;
77
86
  let str = ev.data;
78
87
  this.isComposing || "Backspace" === ev.type || str || (str = "\n"), this.selectionStartCursorIdx > this.cursorIndex && ([this.cursorIndex, this.selectionStartCursorIdx] = [ this.selectionStartCursorIdx, this.cursorIndex ]);
79
88
  const startIdx = findConfigIndexByCursorIdx(textConfig, this.selectionStartCursorIdx), endIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex);
80
89
  let lastConfig = textConfig[this.isComposing ? this.composingConfigIdx : Math.max(startIdx - 1, 0)];
81
- lastConfig || (lastConfig = {
82
- fill: null !== (_a = rest.fill) && void 0 !== _a ? _a : "black",
83
- stroke: null !== (_b = rest.stroke) && void 0 !== _b && _b,
84
- fontSize: null !== (_c = rest.fontSize) && void 0 !== _c ? _c : 12,
85
- fontWeight: null !== (_d = rest.fontWeight) && void 0 !== _d ? _d : "normal"
86
- });
90
+ lastConfig || (lastConfig = getDefaultCharacterConfig(rest));
87
91
  let nextConfig = lastConfig;
88
92
  startIdx !== endIdx && (textConfig.splice(startIdx, endIdx - startIdx), this.isComposing && (this.composingConfigIdx = startIdx));
89
93
  let nextConfigIdx = startIdx;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugins/builtin-plugin/edit-module.ts"],"names":[],"mappings":"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","file":"edit-module.js","sourcesContent":["import { application } from '../../application';\nimport type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface';\n\n// function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) {\n// let idx = 0;\n// for (let i = 0; i < textConfig.length; i++) {\n// const c = textConfig[i] as IRichTextParagraphCharacter;\n// if (c.text !== '\\n') {\n// idx++;\n// }\n// }\n// return Math.max(idx - 1, 0);\n// }\n\n/**\n * 找到cursorIndex所在的textConfig的位置,给出的index就是要插入的准确位置\n * @param textConfig\n * @param cursorIndex\n * @returns\n */\nexport function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number {\n if (cursorIndex < 0) {\n return 0;\n }\n\n // 排序找到对应的元素\n const intCursorIndex = Math.round(cursorIndex);\n let tempCursorIndex = intCursorIndex;\n // 跳过连续换行符中的第一个换行符\n let lineBreak = false;\n let configIdx = 0;\n for (configIdx = 0; configIdx < textConfig.length && tempCursorIndex >= 0; configIdx++) {\n const c = textConfig[configIdx] as IRichTextParagraphCharacter;\n if (c.text === '\\n') {\n tempCursorIndex -= Number(lineBreak);\n lineBreak = true;\n } else {\n tempCursorIndex--;\n lineBreak = false;\n }\n }\n // 说明过限了\n if (tempCursorIndex >= 0) {\n return textConfig.length;\n }\n configIdx -= 1;\n\n // 如果有换行,一定在换行符左边写\n if (cursorIndex > intCursorIndex && !lineBreak) {\n configIdx += 1;\n }\n return configIdx;\n}\n\n/**\n * 根据configIndex找到cursorIndex的位置,忽略单个换行符,连续换行符的时候只忽略第一个\n * @param textConfig\n * @param configIndex\n * @returns\n */\nexport function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number {\n let cursorIndex = 0;\n if (configIndex < 0) {\n return -0.1;\n }\n // 仅有一个\\n,那不算\n // 如果有连续的\\n,那就少算一个\n let lastLineBreak = false;\n\n for (let i = 0; i <= configIndex && i < textConfig.length; i++) {\n const c = textConfig[i] as IRichTextParagraphCharacter;\n if (c.text === '\\n') {\n cursorIndex += Number(lastLineBreak);\n lastLineBreak = true;\n } else {\n cursorIndex++;\n lastLineBreak = false;\n }\n }\n cursorIndex = Math.max(cursorIndex - 1, 0);\n\n // 超出区间了直接设置到尾部,configIndex超过区间,cursorIndex不会超过\n if (configIndex > textConfig.length - 1) {\n // 如果最后一行是一个换行符,那么就得是xx.9否则就是xx.1\n if ((textConfig[textConfig.length - 1] as any)?.text === '\\n') {\n return cursorIndex + 0.9;\n }\n return cursorIndex + 0.1;\n }\n\n // 如果是这个configIdx对应到的是单个换行的话,那么算到下一个字符上\n const lineBreak = (textConfig[configIndex] as any)?.text === '\\n';\n if (configIndex >= textConfig.length - 1 && lineBreak) {\n return cursorIndex + 1 - 0.1;\n }\n const singleLineBreak = lineBreak && (textConfig[configIndex - 1] as any)?.text !== '\\n';\n\n // 光标往左放\n cursorIndex -= 0.1;\n\n // 如果是单行,那么这一个换行符没有算字符,光标要往右放\n if (singleLineBreak) {\n cursorIndex += 0.2;\n }\n return cursorIndex;\n}\n\nexport class EditModule {\n container: HTMLElement;\n textAreaDom: HTMLTextAreaElement;\n currRt: IRichText;\n isComposing: boolean;\n composingConfigIdx: number;\n cursorIndex: number;\n selectionStartCursorIdx: number;\n // 输入的回调(composing的时候每次也会触发)\n onInputCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;\n // change的回调(composing确认才会触发)\n onChangeCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;\n onFocusInList: Array<() => void>;\n onFocusOutList: Array<() => void>;\n focusOutTimer: number;\n\n constructor(container?: HTMLElement) {\n this.container = container ?? document.body;\n\n const textAreaDom = document.createElement('textarea');\n textAreaDom.autocomplete = 'off';\n textAreaDom.innerText = '';\n this.applyStyle(textAreaDom);\n this.container.append(textAreaDom);\n this.textAreaDom = textAreaDom;\n this.isComposing = false;\n this.composingConfigIdx = -1;\n this.onInputCbList = [];\n this.onChangeCbList = [];\n this.onFocusInList = [];\n this.onFocusOutList = [];\n }\n\n onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) {\n this.onInputCbList.push(cb);\n }\n\n onChange(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) {\n this.onChangeCbList.push(cb);\n }\n\n onFocusIn(cb: () => void) {\n this.onFocusInList.push(cb);\n }\n\n onFocusOut(cb: () => void) {\n this.onFocusOutList.push(cb);\n }\n\n applyStyle(textAreaDom: HTMLTextAreaElement) {\n textAreaDom.setAttribute(\n 'style',\n `width: 100px; height: 30px; left: 0; top: 0; position: absolute; z-index: -1; outline: none; resize: none; border: none; overflow: hidden; color: transparent; user-select: none; caret-color: transparent;background-color: transparent;`\n );\n\n textAreaDom.addEventListener('input', this.handleInput);\n textAreaDom.addEventListener('compositionstart', this.handleCompositionStart);\n textAreaDom.addEventListener('compositionend', this.handleCompositionEnd);\n // 监听焦点\n textAreaDom.addEventListener('focusin', this.handleFocusIn);\n textAreaDom.addEventListener('focusout', this.handleFocusOut);\n application.global.addEventListener('keydown', this.handleKeyDown);\n }\n\n handleFocusIn = () => {\n // this.focusOutTimer && clearTimeout(this.focusOutTimer);\n // this.focusOutTimer = 0;\n // this.onFocusInList && this.onFocusInList.forEach(cb => cb());\n };\n handleFocusOut = () => {\n // 暂时注释,会导致非期待情况下的误关闭\n // // 延时触发,避免误关闭\n // this.focusOutTimer = setTimeout(() => {\n // this.onFocusOutList && this.onFocusOutList.forEach(cb => cb());\n // }, 100);\n };\n\n handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Delete' || e.key === 'Backspace') {\n this.handleInput({ data: null, type: 'Backspace' });\n }\n };\n\n handleCompositionStart = () => {\n this.isComposing = true;\n const { textConfig = [] } = this.currRt.attribute;\n this.composingConfigIdx = this.cursorIndex < 0 ? 0 : findConfigIndexByCursorIdx(textConfig, this.cursorIndex);\n if (this.cursorIndex < 0) {\n const config = textConfig[0];\n textConfig.unshift({ fill: 'black', ...config, text: '' });\n } else {\n const configIdx = this.composingConfigIdx;\n const lastConfig = textConfig[configIdx] || textConfig[configIdx - 1];\n textConfig.splice(configIdx, 0, { ...lastConfig, text: '' });\n }\n };\n handleCompositionEnd = () => {\n this.isComposing = false;\n\n const text = this.parseCompositionStr(this.composingConfigIdx);\n // 拆分上一次的内容\n // const { textConfig = [] } = this.currRt.attribute;\n // const configIdx = this.composingConfigIdx;\n\n // const lastConfig = textConfig[configIdx];\n // textConfig.splice(configIdx, 1);\n // const text = (lastConfig as any).text;\n // const textList: string[] = text ? Array.from(text.toString()) : [];\n // for (let i = 0; i < textList.length; i++) {\n // textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any);\n // }\n // this.currRt.setAttributes({ textConfig });\n // const nextConfigIdx = configIdx + textList.length;\n // this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n this.composingConfigIdx = -1;\n\n this.onChangeCbList.forEach(cb => {\n cb(\n text,\n this.isComposing,\n // TODO 当换行后刚开始输入会有问题,后续看这里具体Cursor变换逻辑\n this.cursorIndex,\n this.currRt\n );\n });\n };\n\n /**\n * 复合输入以及粘贴,都会复制出一大段内容,这时候需要重新处理textConfig和cursorIndex\n * 1. 拆分text到textConfig\n * 2. 计算新的cursorIndex\n * @param configIdx\n */\n parseCompositionStr(configIdx: number) {\n const { textConfig = [] } = this.currRt.attribute;\n\n const lastConfig = textConfig[configIdx];\n textConfig.splice(configIdx, 1);\n const text = (lastConfig as any).text;\n const textList: string[] = text ? Array.from(text.toString()) : [];\n for (let i = 0; i < textList.length; i++) {\n textConfig.splice(i + configIdx, 0, {\n fill: 'black',\n ...lastConfig,\n isComposing: false,\n text: textList[i]\n } as any);\n }\n this.currRt.setAttributes({ textConfig });\n const nextConfigIdx = configIdx + textList.length;\n this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n return text;\n }\n\n handleInput = (ev: any) => {\n if (!this.currRt) {\n return;\n }\n if (ev.inputType === 'historyUndo') {\n return;\n }\n const { textConfig = [], ...rest } = this.currRt.attribute;\n // 删完了,直接返回\n if (ev.type === 'Backspace' && !textConfig.length) {\n return;\n }\n\n let str = (ev as any).data;\n if (!this.isComposing && ev.type !== 'Backspace' && !str) {\n str = '\\n';\n }\n\n // 处理正反选\n if (this.selectionStartCursorIdx > this.cursorIndex) {\n [this.cursorIndex, this.selectionStartCursorIdx] = [this.selectionStartCursorIdx, this.cursorIndex];\n }\n\n const startIdx = findConfigIndexByCursorIdx(textConfig, this.selectionStartCursorIdx);\n const endIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex);\n\n // composing的话会插入一个字符,所以往右加一个\n const lastConfigIdx = this.isComposing ? this.composingConfigIdx : Math.max(startIdx - 1, 0);\n // 算一个默认属性\n let lastConfig: any = textConfig[lastConfigIdx];\n if (!lastConfig) {\n lastConfig = {\n fill: rest.fill ?? 'black',\n stroke: rest.stroke ?? false,\n fontSize: rest.fontSize ?? 12,\n fontWeight: rest.fontWeight ?? 'normal'\n };\n }\n let nextConfig = lastConfig;\n\n if (startIdx !== endIdx) {\n textConfig.splice(startIdx, endIdx - startIdx);\n if (this.isComposing) {\n this.composingConfigIdx = startIdx;\n }\n }\n\n let nextConfigIdx = startIdx;\n\n // 删除键\n if (ev.type === 'Backspace' && !this.isComposing) {\n if (startIdx === endIdx) {\n if (startIdx <= 0) {\n return;\n }\n // 删除\n textConfig.splice(startIdx - 1, 1);\n nextConfigIdx = Math.max(startIdx - 1, 0);\n } else {\n // 不插入内容\n }\n } else {\n // 插入\n if (!this.isComposing) {\n nextConfig = { fill: 'black', ...lastConfig, text: '' };\n textConfig.splice(startIdx, 0, nextConfig);\n nextConfigIdx++;\n }\n // 插入\n nextConfig.text = str;\n // 标记isComposing,用来判定是否应该拆分成单个字符\n nextConfig.isComposing = this.isComposing;\n }\n\n this.currRt.setAttributes({ textConfig });\n // 重新计算cursorIdx\n // nextConfigIdx = Math.min(nextConfigIdx, textConfig.length - 1);\n\n let cursorIndex = this.cursorIndex;\n if (str && str.length > 1 && !this.isComposing) {\n // 如果字符长度大于1且不是composing,那说明是粘贴\n // 拆分\n this.parseCompositionStr(nextConfigIdx - 1);\n cursorIndex = this.cursorIndex;\n } else {\n // composing的时候不偏移,只有完整输入后才偏移\n cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n if (!this.isComposing) {\n this.cursorIndex = cursorIndex;\n } else {\n this.cursorIndex = this.selectionStartCursorIdx;\n }\n }\n\n if (!this.isComposing) {\n this.onChangeCbList.forEach(cb => {\n cb(str, this.isComposing, cursorIndex, this.currRt);\n });\n } else {\n this.onInputCbList.forEach(cb => {\n cb(str, this.isComposing, cursorIndex, this.currRt);\n });\n }\n };\n\n moveTo(x: number, y: number, rt: IRichText, cursorIndex: number, selectionStartCursorIdx: number) {\n this.textAreaDom.style.left = `${x}px`;\n this.textAreaDom.style.top = `${y}px`;\n setTimeout(() => {\n this.textAreaDom.focus();\n this.textAreaDom.setSelectionRange(0, 0);\n });\n this.currRt = rt;\n\n this.cursorIndex = cursorIndex;\n this.selectionStartCursorIdx = selectionStartCursorIdx;\n }\n\n release() {\n this.textAreaDom.removeEventListener('input', this.handleInput);\n this.textAreaDom.removeEventListener('compositionstart', this.handleCompositionStart);\n this.textAreaDom.removeEventListener('compositionend', this.handleCompositionEnd);\n this.textAreaDom.addEventListener('focusin', this.handleFocusOut);\n this.textAreaDom.addEventListener('focusout', this.handleFocusOut);\n application.global.removeEventListener('keydown', this.handleKeyDown);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/plugins/builtin-plugin/edit-module.ts"],"names":[],"mappings":"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","file":"edit-module.js","sourcesContent":["import { application } from '../../application';\nimport type {\n IRichText,\n IRichTextCharacter,\n IRichTextGraphicAttribute,\n IRichTextParagraphCharacter\n} from '../../interface';\n\n// function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) {\n// let idx = 0;\n// for (let i = 0; i < textConfig.length; i++) {\n// const c = textConfig[i] as IRichTextParagraphCharacter;\n// if (c.text !== '\\n') {\n// idx++;\n// }\n// }\n// return Math.max(idx - 1, 0);\n// }\n\nexport function getDefaultCharacterConfig(attribute: IRichTextGraphicAttribute) {\n const { fill = 'black', stroke = false, fontWeight = 'normal', fontFamily = 'Arial' } = attribute;\n let { fontSize = 12 } = attribute;\n if (!isFinite(fontSize)) {\n fontSize = 12;\n }\n return {\n fill,\n stroke,\n fontSize,\n fontWeight,\n fontFamily\n } as any;\n}\n\n/**\n * 找到cursorIndex所在的textConfig的位置,给出的index就是要插入的准确位置\n * @param textConfig\n * @param cursorIndex\n * @returns\n */\nexport function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number {\n if (cursorIndex < 0) {\n return 0;\n }\n\n // 排序找到对应的元素\n const intCursorIndex = Math.round(cursorIndex);\n let tempCursorIndex = intCursorIndex;\n // 跳过连续换行符中的第一个换行符\n let lineBreak = false;\n let configIdx = 0;\n for (configIdx = 0; configIdx < textConfig.length && tempCursorIndex >= 0; configIdx++) {\n const c = textConfig[configIdx] as IRichTextParagraphCharacter;\n if (c.text === '\\n') {\n tempCursorIndex -= Number(lineBreak);\n lineBreak = true;\n } else {\n tempCursorIndex--;\n lineBreak = false;\n }\n }\n // 说明过限了\n if (tempCursorIndex >= 0) {\n return textConfig.length;\n }\n configIdx -= 1;\n\n // 如果有换行,一定在换行符左边写\n if (cursorIndex > intCursorIndex && !lineBreak) {\n configIdx += 1;\n }\n return configIdx;\n}\n\n/**\n * 根据configIndex找到cursorIndex的位置,忽略单个换行符,连续换行符的时候只忽略第一个\n * @param textConfig\n * @param configIndex\n * @returns\n */\nexport function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number {\n let cursorIndex = 0;\n if (configIndex < 0) {\n return -0.1;\n }\n // 仅有一个\\n,那不算\n // 如果有连续的\\n,那就少算一个\n let lastLineBreak = false;\n\n for (let i = 0; i <= configIndex && i < textConfig.length; i++) {\n const c = textConfig[i] as IRichTextParagraphCharacter;\n if (c.text === '\\n') {\n cursorIndex += Number(lastLineBreak);\n lastLineBreak = true;\n } else {\n cursorIndex++;\n lastLineBreak = false;\n }\n }\n cursorIndex = Math.max(cursorIndex - 1, 0);\n\n // 超出区间了直接设置到尾部,configIndex超过区间,cursorIndex不会超过\n if (configIndex > textConfig.length - 1) {\n // 如果最后一行是一个换行符,那么就得是xx.9否则就是xx.1\n if ((textConfig[textConfig.length - 1] as any)?.text === '\\n') {\n return cursorIndex + 0.9;\n }\n return cursorIndex + 0.1;\n }\n\n // 如果是这个configIdx对应到的是单个换行的话,那么算到下一个字符上\n const lineBreak = (textConfig[configIndex] as any)?.text === '\\n';\n if (configIndex >= textConfig.length - 1 && lineBreak) {\n return cursorIndex + 1 - 0.1;\n }\n const singleLineBreak = lineBreak && (textConfig[configIndex - 1] as any)?.text !== '\\n';\n\n // 光标往左放\n cursorIndex -= 0.1;\n\n // 如果是单行,那么这一个换行符没有算字符,光标要往右放\n if (singleLineBreak) {\n cursorIndex += 0.2;\n }\n return cursorIndex;\n}\n\nexport class EditModule {\n container: HTMLElement;\n textAreaDom: HTMLTextAreaElement;\n currRt: IRichText;\n isComposing: boolean;\n composingConfigIdx: number;\n cursorIndex: number;\n selectionStartCursorIdx: number;\n // 输入的回调(composing的时候每次也会触发)\n onInputCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;\n // change的回调(composing确认才会触发)\n onChangeCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;\n onFocusInList: Array<() => void>;\n onFocusOutList: Array<() => void>;\n focusOutTimer: number;\n\n constructor(container?: HTMLElement) {\n this.container = container ?? document.body;\n\n const textAreaDom = document.createElement('textarea');\n textAreaDom.autocomplete = 'off';\n textAreaDom.innerText = '';\n this.applyStyle(textAreaDom);\n this.container.append(textAreaDom);\n this.textAreaDom = textAreaDom;\n this.isComposing = false;\n this.composingConfigIdx = -1;\n this.onInputCbList = [];\n this.onChangeCbList = [];\n this.onFocusInList = [];\n this.onFocusOutList = [];\n }\n\n onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) {\n this.onInputCbList.push(cb);\n }\n\n onChange(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) {\n this.onChangeCbList.push(cb);\n }\n\n onFocusIn(cb: () => void) {\n this.onFocusInList.push(cb);\n }\n\n onFocusOut(cb: () => void) {\n this.onFocusOutList.push(cb);\n }\n\n applyStyle(textAreaDom: HTMLTextAreaElement) {\n textAreaDom.setAttribute(\n 'style',\n `width: 100px; height: 30px; left: 0; top: 0; position: absolute; z-index: -1; outline: none; resize: none; border: none; overflow: hidden; color: transparent; user-select: none; caret-color: transparent;background-color: transparent;`\n );\n\n textAreaDom.addEventListener('input', this.handleInput);\n textAreaDom.addEventListener('compositionstart', this.handleCompositionStart);\n textAreaDom.addEventListener('compositionend', this.handleCompositionEnd);\n // 监听焦点\n textAreaDom.addEventListener('focusin', this.handleFocusIn);\n textAreaDom.addEventListener('focusout', this.handleFocusOut);\n application.global.addEventListener('keydown', this.handleKeyDown);\n }\n\n handleFocusIn = () => {\n // this.focusOutTimer && clearTimeout(this.focusOutTimer);\n // this.focusOutTimer = 0;\n // this.onFocusInList && this.onFocusInList.forEach(cb => cb());\n };\n handleFocusOut = () => {\n // 暂时注释,会导致非期待情况下的误关闭\n // // 延时触发,避免误关闭\n // this.focusOutTimer = setTimeout(() => {\n // this.onFocusOutList && this.onFocusOutList.forEach(cb => cb());\n // }, 100);\n };\n\n handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Delete' || e.key === 'Backspace') {\n this.handleInput({ data: null, type: 'Backspace' });\n }\n };\n\n handleCompositionStart = () => {\n this.isComposing = true;\n const { textConfig = [] } = this.currRt.attribute;\n this.composingConfigIdx = this.cursorIndex < 0 ? 0 : findConfigIndexByCursorIdx(textConfig, this.cursorIndex);\n if (this.cursorIndex < 0) {\n const config = textConfig[0];\n textConfig.unshift({ ...getDefaultCharacterConfig(this.currRt.attribute), ...config, text: '' });\n } else {\n const configIdx = this.composingConfigIdx;\n const lastConfig = textConfig[configIdx] || textConfig[configIdx - 1];\n textConfig.splice(configIdx, 0, { ...lastConfig, text: '' });\n }\n };\n handleCompositionEnd = () => {\n this.isComposing = false;\n\n const text = this.parseCompositionStr(this.composingConfigIdx);\n // 拆分上一次的内容\n // const { textConfig = [] } = this.currRt.attribute;\n // const configIdx = this.composingConfigIdx;\n\n // const lastConfig = textConfig[configIdx];\n // textConfig.splice(configIdx, 1);\n // const text = (lastConfig as any).text;\n // const textList: string[] = text ? Array.from(text.toString()) : [];\n // for (let i = 0; i < textList.length; i++) {\n // textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any);\n // }\n // this.currRt.setAttributes({ textConfig });\n // const nextConfigIdx = configIdx + textList.length;\n // this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n this.composingConfigIdx = -1;\n\n this.onChangeCbList.forEach(cb => {\n cb(\n text,\n this.isComposing,\n // TODO 当换行后刚开始输入会有问题,后续看这里具体Cursor变换逻辑\n this.cursorIndex,\n this.currRt\n );\n });\n };\n\n /**\n * 复合输入以及粘贴,都会复制出一大段内容,这时候需要重新处理textConfig和cursorIndex\n * 1. 拆分text到textConfig\n * 2. 计算新的cursorIndex\n * @param configIdx\n */\n parseCompositionStr(configIdx: number) {\n const { textConfig = [] } = this.currRt.attribute;\n\n const lastConfig = textConfig[configIdx];\n textConfig.splice(configIdx, 1);\n const text = (lastConfig as any).text;\n const textList: string[] = text ? Array.from(text.toString()) : [];\n for (let i = 0; i < textList.length; i++) {\n textConfig.splice(i + configIdx, 0, {\n fill: 'black',\n ...lastConfig,\n isComposing: false,\n text: textList[i]\n } as any);\n }\n this.currRt.setAttributes({ textConfig });\n const nextConfigIdx = configIdx + textList.length;\n this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n return text;\n }\n\n handleInput = (ev: any) => {\n if (!this.currRt) {\n return;\n }\n if (ev.inputType === 'historyUndo') {\n return;\n }\n const { textConfig = [], ...rest } = this.currRt.attribute;\n // 删完了,直接返回\n if (ev.type === 'Backspace' && !textConfig.length) {\n return;\n }\n\n let str = (ev as any).data;\n if (!this.isComposing && ev.type !== 'Backspace' && !str) {\n str = '\\n';\n }\n\n // 处理正反选\n if (this.selectionStartCursorIdx > this.cursorIndex) {\n [this.cursorIndex, this.selectionStartCursorIdx] = [this.selectionStartCursorIdx, this.cursorIndex];\n }\n\n const startIdx = findConfigIndexByCursorIdx(textConfig, this.selectionStartCursorIdx);\n const endIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex);\n\n // composing的话会插入一个字符,所以往右加一个\n const lastConfigIdx = this.isComposing ? this.composingConfigIdx : Math.max(startIdx - 1, 0);\n // 算一个默认属性\n let lastConfig: any = textConfig[lastConfigIdx];\n if (!lastConfig) {\n lastConfig = getDefaultCharacterConfig(rest);\n }\n let nextConfig = lastConfig;\n\n if (startIdx !== endIdx) {\n textConfig.splice(startIdx, endIdx - startIdx);\n if (this.isComposing) {\n this.composingConfigIdx = startIdx;\n }\n }\n\n let nextConfigIdx = startIdx;\n\n // 删除键\n if (ev.type === 'Backspace' && !this.isComposing) {\n if (startIdx === endIdx) {\n if (startIdx <= 0) {\n return;\n }\n // 删除\n textConfig.splice(startIdx - 1, 1);\n nextConfigIdx = Math.max(startIdx - 1, 0);\n } else {\n // 不插入内容\n }\n } else {\n // 插入\n if (!this.isComposing) {\n nextConfig = { fill: 'black', ...lastConfig, text: '' };\n textConfig.splice(startIdx, 0, nextConfig);\n nextConfigIdx++;\n }\n // 插入\n nextConfig.text = str;\n // 标记isComposing,用来判定是否应该拆分成单个字符\n nextConfig.isComposing = this.isComposing;\n }\n\n this.currRt.setAttributes({ textConfig });\n // 重新计算cursorIdx\n // nextConfigIdx = Math.min(nextConfigIdx, textConfig.length - 1);\n\n let cursorIndex = this.cursorIndex;\n if (str && str.length > 1 && !this.isComposing) {\n // 如果字符长度大于1且不是composing,那说明是粘贴\n // 拆分\n this.parseCompositionStr(nextConfigIdx - 1);\n cursorIndex = this.cursorIndex;\n } else {\n // composing的时候不偏移,只有完整输入后才偏移\n cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx);\n if (!this.isComposing) {\n this.cursorIndex = cursorIndex;\n } else {\n this.cursorIndex = this.selectionStartCursorIdx;\n }\n }\n\n if (!this.isComposing) {\n this.onChangeCbList.forEach(cb => {\n cb(str, this.isComposing, cursorIndex, this.currRt);\n });\n } else {\n this.onInputCbList.forEach(cb => {\n cb(str, this.isComposing, cursorIndex, this.currRt);\n });\n }\n };\n\n moveTo(x: number, y: number, rt: IRichText, cursorIndex: number, selectionStartCursorIdx: number) {\n this.textAreaDom.style.left = `${x}px`;\n this.textAreaDom.style.top = `${y}px`;\n setTimeout(() => {\n this.textAreaDom.focus();\n this.textAreaDom.setSelectionRange(0, 0);\n });\n this.currRt = rt;\n\n this.cursorIndex = cursorIndex;\n this.selectionStartCursorIdx = selectionStartCursorIdx;\n }\n\n release() {\n this.textAreaDom.removeEventListener('input', this.handleInput);\n this.textAreaDom.removeEventListener('compositionstart', this.handleCompositionStart);\n this.textAreaDom.removeEventListener('compositionend', this.handleCompositionEnd);\n this.textAreaDom.addEventListener('focusin', this.handleFocusOut);\n this.textAreaDom.addEventListener('focusout', this.handleFocusOut);\n application.global.removeEventListener('keydown', this.handleKeyDown);\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { IPointLike } from '@visactor/vutils';
2
- import type { IGroup, ILine, IPlugin, IPluginService, IRichText, IRichTextFrame, IRichTextIcon, IRichTextLine, IRichTextParagraph, ITicker, ITimeline } from '../../interface';
2
+ import type { IGroup, ILine, IPlugin, IPluginService, IRect, IRichText, IRichTextCharacter, IRichTextFrame, IRichTextIcon, IRichTextLine, IRichTextParagraph, ITicker, ITimeline } from '../../interface';
3
3
  import { EditModule } from './edit-module';
4
4
  type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch';
5
5
  declare class Selection {
@@ -15,6 +15,7 @@ declare class Selection {
15
15
  getAllFormat(key: string): any;
16
16
  }
17
17
  export declare const FORMAT_TEXT_COMMAND = "FORMAT_TEXT_COMMAND";
18
+ export declare const FORMAT_ALL_TEXT_COMMAND = "FORMAT_ALL_TEXT_COMMAND";
18
19
  export declare const FORMAT_ELEMENT_COMMAND = "FORMAT_ELEMENT_COMMAND";
19
20
  export declare class RichTextEditPlugin implements IPlugin {
20
21
  name: 'RichTextEditPlugin';
@@ -23,9 +24,12 @@ export declare class RichTextEditPlugin implements IPlugin {
23
24
  _uid: number;
24
25
  key: string;
25
26
  editing: boolean;
27
+ focusing: boolean;
26
28
  pointerDown: boolean;
27
29
  editLine: ILine;
28
30
  editBg: IGroup;
31
+ shadowPlaceHolder: IRichText;
32
+ shadowBounds: IRect;
29
33
  ticker: ITicker;
30
34
  timeline: ITimeline;
31
35
  currRt: IRichText;
@@ -40,20 +44,28 @@ export declare class RichTextEditPlugin implements IPlugin {
40
44
  static tryUpdateRichtext(richtext: IRichText): void;
41
45
  static CreateSelection(rt: IRichText): Selection;
42
46
  constructor();
43
- formatTextCommandCb(payload: string, p: RichTextEditPlugin): void;
47
+ formatTextCommandCb: (payload: string, p: RichTextEditPlugin) => void;
48
+ formatAllTextCommandCb: (payload: string, p: RichTextEditPlugin) => void;
49
+ _formatTextCommand(payload: string, config: IRichTextCharacter[], rt: IRichText): void;
44
50
  dispatchCommand(command: string, payload: any): void;
45
51
  registerCommand(command: string, cb: (payload: any, p: RichTextEditPlugin) => void): void;
52
+ removeCommand(command: string, cb: (payload: any, p: RichTextEditPlugin) => void): void;
46
53
  registerUpdateListener(cb: (type: UpdateType, p: RichTextEditPlugin) => void): void;
54
+ removeUpdateListener(cb: (type: UpdateType, p: RichTextEditPlugin) => void): void;
47
55
  activate(context: IPluginService): void;
48
56
  copyToClipboard(e: KeyboardEvent): boolean;
49
57
  selectionRange(startIdx: number, endIdx: number): void;
58
+ selectionRangeByCursorIdx(startCursorIdx: number, endCursorIdx: number, cache: IRichTextFrame): void;
50
59
  fullSelection(e: KeyboardEvent): boolean;
51
60
  directKey(e: KeyboardEvent): boolean;
52
61
  handleKeyDown: (e: KeyboardEvent) => void;
53
62
  handleInput: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void;
54
63
  handleChange: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void;
55
- handleFocusIn: () => void;
56
- handleFocusOut: () => void;
64
+ tryShowShadowPlaceholder(): void;
65
+ tryShowInputBounds(): void;
66
+ trySyncPlaceholderToTextConfig(): void;
67
+ handleFocusIn: () => never;
68
+ handleFocusOut: () => never;
57
69
  deactivate(context: IPluginService): void;
58
70
  handleMove: (e: PointerEvent) => void;
59
71
  handleEnter: (e: PointerEvent) => void;
@@ -61,8 +73,9 @@ export declare class RichTextEditPlugin implements IPlugin {
61
73
  handlePointerDown: (e: PointerEvent) => void;
62
74
  handlePointerUp: (e: PointerEvent) => void;
63
75
  handleDBLClick: (e: PointerEvent) => void;
64
- onFocus(e: PointerEvent): void;
65
- protected deFocus(): void;
76
+ onFocus(e: PointerEvent, data?: any): void;
77
+ protected offsetLineBgAndShadowBounds(): void;
78
+ protected deFocus(trulyDeFocus?: boolean): void;
66
79
  protected addAnimateToLine(line: ILine): void;
67
80
  tryShowSelection(e: PointerEvent, dblclick: boolean): void;
68
81
  _tryShowSelection(currCursorData: {
@@ -94,10 +107,14 @@ export declare class RichTextEditPlugin implements IPlugin {
94
107
  x: number;
95
108
  y1: number;
96
109
  y2: any;
110
+ lineInfo?: undefined;
111
+ columnInfo?: undefined;
97
112
  } | {
98
113
  x: any;
99
114
  y1: number;
100
115
  y2: number;
116
+ lineInfo: IRichTextLine;
117
+ columnInfo: IRichTextParagraph | IRichTextIcon;
101
118
  };
102
119
  protected getColumnByIndex(cache: IRichTextFrame, index: number): {
103
120
  lineInfo: IRichTextLine;
@@ -105,5 +122,12 @@ export declare class RichTextEditPlugin implements IPlugin {
105
122
  } | null;
106
123
  release(): void;
107
124
  getSelection(defaultAll?: boolean): Selection;
125
+ forceFocus(params: {
126
+ e?: PointerEvent;
127
+ target: IRichText | null;
128
+ cursorIndex?: number;
129
+ }): void;
130
+ protected _forceFocusByEvent(e: PointerEvent): void;
131
+ protected _forceFocusByCursorIndex(cursorIndex: number): void;
108
132
  }
109
133
  export {};