@visactor/vrender-core 0.22.0-vstory.5 → 0.22.0-vstory.7

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 (42) hide show
  1. package/cjs/animate/custom-animate.js +2 -1
  2. package/cjs/animate/index.js +1 -2
  3. package/cjs/graphic/builtin-symbol/utils.js +1 -1
  4. package/cjs/graphic/builtin-symbol/utils.js.map +1 -1
  5. package/cjs/graphic/group.js +1 -1
  6. package/cjs/graphic/group.js.map +1 -1
  7. package/cjs/graphic/richtext/paragraph.js +4 -5
  8. package/cjs/graphic/richtext/paragraph.js.map +1 -1
  9. package/cjs/graphic/richtext.d.ts +2 -1
  10. package/cjs/graphic/richtext.js +6 -0
  11. package/cjs/graphic/richtext.js.map +1 -1
  12. package/cjs/interface/graphic/richText.d.ts +1 -0
  13. package/cjs/interface/graphic/richText.js.map +1 -1
  14. package/cjs/plugins/builtin-plugin/edit-module.js +2 -2
  15. package/cjs/plugins/builtin-plugin/edit-module.js.map +1 -1
  16. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.d.ts +3 -2
  17. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js +87 -73
  18. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  19. package/cjs/render/contributions/render/draw-contribution.js +1 -1
  20. package/cjs/render/contributions/render/draw-contribution.js.map +1 -1
  21. package/dist/index.es.js +56 -21
  22. package/es/animate/custom-animate.js +2 -1
  23. package/es/animate/index.js +1 -2
  24. package/es/graphic/builtin-symbol/utils.js +1 -1
  25. package/es/graphic/builtin-symbol/utils.js.map +1 -1
  26. package/es/graphic/group.js +1 -1
  27. package/es/graphic/group.js.map +1 -1
  28. package/es/graphic/richtext/paragraph.js +4 -5
  29. package/es/graphic/richtext/paragraph.js.map +1 -1
  30. package/es/graphic/richtext.d.ts +2 -1
  31. package/es/graphic/richtext.js +6 -0
  32. package/es/graphic/richtext.js.map +1 -1
  33. package/es/interface/graphic/richText.d.ts +1 -0
  34. package/es/interface/graphic/richText.js.map +1 -1
  35. package/es/plugins/builtin-plugin/edit-module.js +2 -2
  36. package/es/plugins/builtin-plugin/edit-module.js.map +1 -1
  37. package/es/plugins/builtin-plugin/richtext-edit-plugin.d.ts +3 -2
  38. package/es/plugins/builtin-plugin/richtext-edit-plugin.js +85 -73
  39. package/es/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  40. package/es/render/contributions/render/draw-contribution.js +1 -1
  41. package/es/render/contributions/render/draw-contribution.js.map +1 -1
  42. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/interface/graphic/richText.ts"],"names":[],"mappings":"","file":"richText.js","sourcesContent":["import type { IColor } from '../color';\nimport type { IContext2d } from '../context';\nimport type { IGraphicAttribute, IGraphic } from '../graphic';\nimport type { IImage, IImageGraphicAttribute } from './image';\nimport type { ITextGraphicAttribute } from './text';\n\nexport type IRichTextEditOptionsType = {\n placeholder?: string;\n placeholderColor?: string;\n placeholderFontSize?: number;\n placeholderFontFamily?: string;\n // 是否将placeholder同步到textConfig中\n syncPlaceholderToTextConfig?: boolean;\n // 即使是空文本,是否也保持高度\n keepHeightWhileEmpty?: boolean;\n // 是否在输入的时候展示包围框,不传默认是false,可以传入颜色\n boundsStrokeWhenInput?: string;\n};\n\nexport type IRichTextAttribute = {\n width: number;\n height: number;\n editable: boolean;\n editOptions: IRichTextEditOptionsType | null;\n ellipsis: boolean | string;\n wordBreak: RichTextWordBreak;\n verticalDirection: RichTextVerticalDirection;\n maxHeight: number;\n maxWidth: number;\n textAlign: RichTextGlobalAlignType;\n textBaseline: RichTextGlobalBaselineType;\n layoutDirection: RichTextLayoutDirectionType;\n textConfig: IRichTextCharacter[];\n // 是否不自动每行截断\n disableAutoWrapLine: boolean;\n singleLine: boolean;\n};\n\nexport type IRichTextGraphicAttribute = Partial<IGraphicAttribute & ITextGraphicAttribute> &\n Partial<IRichTextAttribute>;\n\nexport type RichTextWordBreak = 'break-word' | 'break-all';\nexport type RichTextVerticalDirection = 'top' | 'middle' | 'bottom';\nexport type RichTextGlobalAlignType = 'left' | 'right' | 'center';\nexport type RichTextGlobalBaselineType = 'top' | 'middle' | 'bottom';\nexport type RichTextLayoutDirectionType = 'horizontal' | 'vertical';\nexport type RichTextFontStyle = 'normal' | 'italic' | 'oblique';\nexport type RichTextTextDecoration = 'none' | 'underline' | 'line-through';\n// export type RichTextTextAlign = 'left' | 'right' | 'center';\nexport type RichTextScript = 'normal' | 'sub' | 'super';\n\nexport type IRichTextBasicCharacter = {\n lineHeight?: number | string;\n textAlign?: CanvasTextAlign; // left, right, center\n textBaseline?: CanvasTextBaseline;\n direction?: RichTextLayoutDirectionType;\n};\n\nexport type IRichTextParagraphCharacter = IRichTextBasicCharacter & {\n text: string | number;\n fontSize?: number;\n fontFamily?: string;\n fill?: IColor | boolean;\n stroke?: IColor | boolean;\n fontWeight?: string;\n lineWidth?: number;\n // lineHeight?: number;\n fontStyle?: RichTextFontStyle; // normal, italic, oblique\n textDecoration?: RichTextTextDecoration; // none, underline, line-through\n // textAlign?: RichTextTextAlign; // left, right, center\n script?: RichTextScript; // normal, sub, super\n underline?: boolean;\n lineThrough?: boolean;\n opacity?: number;\n fillOpacity?: number;\n strokeOpacity?: number;\n // 仅支持纯色背景\n background?: string;\n // 背景透明度\n backgroundOpacity?: number;\n // direction?: RichTextLayoutDirectionType;\n};\n\nexport type IRichTextImageCharacter = IRichTextBasicCharacter & {\n // 图片基础属性\n image: string | HTMLImageElement | HTMLCanvasElement;\n width: number;\n height: number;\n\n // hover相关属性\n // backgroundShow?: boolean; // 是否显示background\n backgroundShowMode?: 'always' | 'hover';\n backgroundFill?: boolean | IColor; // 背景矩形填充颜色\n backgroundFillOpacity?: number; // 背景矩形填充透明度\n backgroundStroke?: boolean | IColor; // 背景矩形边框颜色\n backgroundStrokeOpacity?: number; // 背景矩形边框透明度\n backgroundRadius?: number; // 背景矩形圆角\n // background size 同时控制了该icon的响应范围\n backgroundWidth?: number;\n backgroundHeight?: number;\n\n // 唯一标识符\n id?: string;\n\n // lineHeight?: number;\n // textAlign?: RichTextTextAlign; // left, right, center\n // direction?: RichTextLayoutDirectionType;\n margin?: number | number[];\n\n funcType?: string;\n hoverImage?: string | HTMLImageElement | HTMLCanvasElement;\n};\n\nexport type IRichTextCharacter = IRichTextParagraphCharacter | IRichTextImageCharacter;\n\nexport type IRichTextIconGraphicAttribute = IImageGraphicAttribute & {\n id?: string;\n backgroundShowMode?: 'always' | 'hover' | 'never';\n backgroundFill?: boolean | IColor; // 背景矩形填充颜色\n backgroundFillOpacity?: number; // 背景矩形填充透明度\n backgroundStroke?: boolean | IColor; // 背景矩形边框颜色\n backgroundStrokeOpacity?: number; // 背景矩形边框透明度\n backgroundRadius?: number; // 背景矩形圆角\n backgroundWidth?: number;\n backgroundHeight?: number;\n\n // lineHeight?: number;\n textAlign?: CanvasTextAlign; // left, right, center\n textBaseline?: CanvasTextBaseline;\n direction?: RichTextLayoutDirectionType;\n\n margin?: number | number[];\n\n // backgroundShow?: boolean;\n};\n\nexport interface IRichTextParagraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n direction?: 'horizontal' | 'vertical';\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n updateWidth: () => void;\n draw: (ctx: IContext2d, baseline: number, deltaLeft: number, isLineFirst: boolean, textAlign: string) => void;\n getWidthWithEllips: (direction: string) => number;\n}\n\nexport interface IRichTextLine {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (IRichTextParagraph | IRichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: {\n width: string;\n height: string;\n left: string;\n x: string;\n y: string;\n };\n draw: (\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) => void;\n getWidthWithEllips: (ellipsis: string) => number;\n}\n\nexport interface IRichTextFrame {\n left: number;\n top: number;\n bottom: number;\n right: number;\n width: number;\n height: number;\n actualHeight: number;\n ellipsis: boolean | string;\n wordBreak: 'break-word' | 'break-all';\n verticalDirection: 'top' | 'middle' | 'bottom';\n lines: IRichTextLine[];\n globalAlign: 'left' | 'center' | 'right' | 'start' | 'end';\n globalBaseline: 'top' | 'middle' | 'bottom';\n layoutDirection: 'horizontal' | 'vertical';\n directionKey: {\n width: string;\n height: string;\n left: string;\n top: string;\n bottom: string;\n };\n isWidthMax: boolean;\n isHeightMax: boolean;\n singleLine: boolean;\n icons: Map<string, IRichTextIcon>;\n draw: (\n ctx: IContext2d,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) => boolean;\n getActualSize: () => {\n width: number;\n height: number;\n };\n getRawActualSize: () => {\n width: number;\n height: number;\n };\n getActualSizeWidthEllipsis: () => {\n width: number;\n height: number;\n };\n}\n\nexport interface IRichText extends IGraphic<IRichTextGraphicAttribute> {\n getFrameCache: () => IRichTextFrame;\n cliped?: boolean;\n}\n\nexport interface IRichTextIcon extends IImage {\n attribute: IRichTextIconGraphicAttribute;\n richtextId?: string;\n globalX?: number;\n globalY?: number;\n\n _x: number;\n _y: number;\n _hovered: boolean;\n _marginArray: [number, number, number, number];\n\n setHoverState: (hovered: boolean) => void;\n}\n"]}
1
+ {"version":3,"sources":["../src/interface/graphic/richText.ts"],"names":[],"mappings":"","file":"richText.js","sourcesContent":["import type { IColor } from '../color';\nimport type { IContext2d } from '../context';\nimport type { IGraphicAttribute, IGraphic } from '../graphic';\nimport type { IImage, IImageGraphicAttribute } from './image';\nimport type { ITextGraphicAttribute } from './text';\n\nexport type IRichTextEditOptionsType = {\n placeholder?: string;\n syncPlaceHolderToTextConfig?: boolean;\n placeholderColor?: string;\n placeholderFontSize?: number;\n placeholderFontFamily?: string;\n // 是否将placeholder同步到textConfig中\n syncPlaceholderToTextConfig?: boolean;\n // 即使是空文本,是否也保持高度\n keepHeightWhileEmpty?: boolean;\n // 是否在输入的时候展示包围框,不传默认是false,可以传入颜色\n boundsStrokeWhenInput?: string;\n};\n\nexport type IRichTextAttribute = {\n width: number;\n height: number;\n editable: boolean;\n editOptions: IRichTextEditOptionsType | null;\n ellipsis: boolean | string;\n wordBreak: RichTextWordBreak;\n verticalDirection: RichTextVerticalDirection;\n maxHeight: number;\n maxWidth: number;\n textAlign: RichTextGlobalAlignType;\n textBaseline: RichTextGlobalBaselineType;\n layoutDirection: RichTextLayoutDirectionType;\n textConfig: IRichTextCharacter[];\n // 是否不自动每行截断\n disableAutoWrapLine: boolean;\n singleLine: boolean;\n};\n\nexport type IRichTextGraphicAttribute = Partial<IGraphicAttribute & ITextGraphicAttribute> &\n Partial<IRichTextAttribute>;\n\nexport type RichTextWordBreak = 'break-word' | 'break-all';\nexport type RichTextVerticalDirection = 'top' | 'middle' | 'bottom';\nexport type RichTextGlobalAlignType = 'left' | 'right' | 'center';\nexport type RichTextGlobalBaselineType = 'top' | 'middle' | 'bottom';\nexport type RichTextLayoutDirectionType = 'horizontal' | 'vertical';\nexport type RichTextFontStyle = 'normal' | 'italic' | 'oblique';\nexport type RichTextTextDecoration = 'none' | 'underline' | 'line-through';\n// export type RichTextTextAlign = 'left' | 'right' | 'center';\nexport type RichTextScript = 'normal' | 'sub' | 'super';\n\nexport type IRichTextBasicCharacter = {\n lineHeight?: number | string;\n textAlign?: CanvasTextAlign; // left, right, center\n textBaseline?: CanvasTextBaseline;\n direction?: RichTextLayoutDirectionType;\n};\n\nexport type IRichTextParagraphCharacter = IRichTextBasicCharacter & {\n text: string | number;\n fontSize?: number;\n fontFamily?: string;\n fill?: IColor | boolean;\n stroke?: IColor | boolean;\n fontWeight?: string;\n lineWidth?: number;\n // lineHeight?: number;\n fontStyle?: RichTextFontStyle; // normal, italic, oblique\n textDecoration?: RichTextTextDecoration; // none, underline, line-through\n // textAlign?: RichTextTextAlign; // left, right, center\n script?: RichTextScript; // normal, sub, super\n underline?: boolean;\n lineThrough?: boolean;\n opacity?: number;\n fillOpacity?: number;\n strokeOpacity?: number;\n // 仅支持纯色背景\n background?: string;\n // 背景透明度\n backgroundOpacity?: number;\n // direction?: RichTextLayoutDirectionType;\n};\n\nexport type IRichTextImageCharacter = IRichTextBasicCharacter & {\n // 图片基础属性\n image: string | HTMLImageElement | HTMLCanvasElement;\n width: number;\n height: number;\n\n // hover相关属性\n // backgroundShow?: boolean; // 是否显示background\n backgroundShowMode?: 'always' | 'hover';\n backgroundFill?: boolean | IColor; // 背景矩形填充颜色\n backgroundFillOpacity?: number; // 背景矩形填充透明度\n backgroundStroke?: boolean | IColor; // 背景矩形边框颜色\n backgroundStrokeOpacity?: number; // 背景矩形边框透明度\n backgroundRadius?: number; // 背景矩形圆角\n // background size 同时控制了该icon的响应范围\n backgroundWidth?: number;\n backgroundHeight?: number;\n\n // 唯一标识符\n id?: string;\n\n // lineHeight?: number;\n // textAlign?: RichTextTextAlign; // left, right, center\n // direction?: RichTextLayoutDirectionType;\n margin?: number | number[];\n\n funcType?: string;\n hoverImage?: string | HTMLImageElement | HTMLCanvasElement;\n};\n\nexport type IRichTextCharacter = IRichTextParagraphCharacter | IRichTextImageCharacter;\n\nexport type IRichTextIconGraphicAttribute = IImageGraphicAttribute & {\n id?: string;\n backgroundShowMode?: 'always' | 'hover' | 'never';\n backgroundFill?: boolean | IColor; // 背景矩形填充颜色\n backgroundFillOpacity?: number; // 背景矩形填充透明度\n backgroundStroke?: boolean | IColor; // 背景矩形边框颜色\n backgroundStrokeOpacity?: number; // 背景矩形边框透明度\n backgroundRadius?: number; // 背景矩形圆角\n backgroundWidth?: number;\n backgroundHeight?: number;\n\n // lineHeight?: number;\n textAlign?: CanvasTextAlign; // left, right, center\n textBaseline?: CanvasTextBaseline;\n direction?: RichTextLayoutDirectionType;\n\n margin?: number | number[];\n\n // backgroundShow?: boolean;\n};\n\nexport interface IRichTextParagraph {\n text: string;\n ascent: number;\n descent: number;\n width: number;\n height: number;\n lineHeight: number;\n fontSize: number;\n length: number;\n newLine: boolean;\n character: IRichTextParagraphCharacter;\n left: number;\n top: number;\n direction?: 'horizontal' | 'vertical';\n widthOrigin?: number;\n heightOrigin?: number;\n textBaseline?: CanvasTextBaseline;\n ellipsis: 'normal' | 'add' | 'replace' | 'hide';\n ellipsisWidth: number;\n ellipsisOtherParagraphWidth: number;\n verticalEllipsis?: boolean;\n updateWidth: () => void;\n draw: (ctx: IContext2d, baseline: number, deltaLeft: number, isLineFirst: boolean, textAlign: string) => void;\n getWidthWithEllips: (direction: string) => number;\n}\n\nexport interface IRichTextLine {\n left: number;\n top: number;\n width: number;\n height: number;\n baseline: number;\n ascent: number;\n descent: number;\n paragraphs: (IRichTextParagraph | IRichTextIcon)[];\n actualWidth: number;\n blankWidth: number;\n textAlign: string;\n direction: 'horizontal' | 'vertical';\n directionKey: {\n width: string;\n height: string;\n left: string;\n x: string;\n y: string;\n };\n draw: (\n ctx: IContext2d,\n lastLine: boolean,\n x: number,\n y: number,\n drawEllipsis: boolean | string,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) => void;\n getWidthWithEllips: (ellipsis: string) => number;\n}\n\nexport interface IRichTextFrame {\n left: number;\n top: number;\n bottom: number;\n right: number;\n width: number;\n height: number;\n actualHeight: number;\n ellipsis: boolean | string;\n wordBreak: 'break-word' | 'break-all';\n verticalDirection: 'top' | 'middle' | 'bottom';\n lines: IRichTextLine[];\n globalAlign: 'left' | 'center' | 'right' | 'start' | 'end';\n globalBaseline: 'top' | 'middle' | 'bottom';\n layoutDirection: 'horizontal' | 'vertical';\n directionKey: {\n width: string;\n height: string;\n left: string;\n top: string;\n bottom: string;\n };\n isWidthMax: boolean;\n isHeightMax: boolean;\n singleLine: boolean;\n icons: Map<string, IRichTextIcon>;\n draw: (\n ctx: IContext2d,\n drawIcon: (icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) => void\n ) => boolean;\n getActualSize: () => {\n width: number;\n height: number;\n };\n getRawActualSize: () => {\n width: number;\n height: number;\n };\n getActualSizeWidthEllipsis: () => {\n width: number;\n height: number;\n };\n}\n\nexport interface IRichText extends IGraphic<IRichTextGraphicAttribute> {\n getFrameCache: () => IRichTextFrame;\n cliped?: boolean;\n}\n\nexport interface IRichTextIcon extends IImage {\n attribute: IRichTextIconGraphicAttribute;\n richtextId?: string;\n globalX?: number;\n globalY?: number;\n\n _x: number;\n _y: number;\n _hovered: boolean;\n _marginArray: [number, number, number, number];\n\n setHoverState: (hovered: boolean) => void;\n}\n"]}
@@ -150,9 +150,9 @@ class EditModule {
150
150
  const {textConfig: textConfig = []} = this.currRt.attribute, lastConfig = textConfig[configIdx];
151
151
  textConfig.splice(configIdx, 1);
152
152
  const text = lastConfig.text, textList = text ? Array.from(text.toString()) : [];
153
- for (let i = 0; i < textList.length; i++) textConfig.splice(i + configIdx, 0, Object.assign(Object.assign({
153
+ for (let i = 0; i < textList.length; i++) textConfig.splice(i + configIdx, 0, Object.assign(Object.assign(Object.assign(Object.assign({}, getDefaultCharacterConfig(this.currRt.attribute)), {
154
154
  fill: "black"
155
- }, lastConfig), {
155
+ }), lastConfig), {
156
156
  isComposing: !1,
157
157
  text: textList[i]
158
158
  }));
@@ -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 {\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
+ {"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 ...getDefaultCharacterConfig(this.currRt.attribute),\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,7 +1,7 @@
1
1
  import type { IPointLike } from '@visactor/vutils';
2
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
- type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch';
4
+ type UpdateType = 'input' | 'change' | 'onfocus' | 'beforeOnfocus' | 'defocus' | 'beforeDefocus' | 'selection' | 'dispatch';
5
5
  declare class Selection {
6
6
  selectionStartCursorIdx: number;
7
7
  curCursorIdx: number;
@@ -38,7 +38,7 @@ export declare class RichTextEditPlugin implements IPlugin {
38
38
  startCursorPos?: IPointLike;
39
39
  editModule: EditModule;
40
40
  protected commandCbs: Map<string, Array<(payload: any, p: RichTextEditPlugin) => void>>;
41
- protected updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin) => void>;
41
+ protected updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin, params?: any) => void>;
42
42
  protected deltaX: number;
43
43
  protected deltaY: number;
44
44
  static tryUpdateRichtext(richtext: IRichText): void;
@@ -84,6 +84,7 @@ export declare class RichTextEditPlugin implements IPlugin {
84
84
  y2: number;
85
85
  }, cache: IRichTextFrame): void;
86
86
  hideSelection(): void;
87
+ protected getShadow(rt: IRichText): import("../../interface").IShadowRoot;
87
88
  protected getLineByPoint(cache: IRichTextFrame, p1: IPointLike): IRichTextLine;
88
89
  protected getColumnAndIndexByLinePoint(lineInfo: IRichTextLine, p1: IPointLike): {
89
90
  columnInfo: IRichTextParagraph | IRichTextIcon;
@@ -185,7 +185,10 @@ class RichTextEditPlugin {
185
185
  if (!currRt) return;
186
186
  const cache = currRt.getFrameCache();
187
187
  if (!cache) return;
188
- const {lines: lines} = cache, totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
188
+ const {lines: lines} = cache;
189
+ if (0 === lines.length) return;
190
+ if (!lines[0].paragraphs || 0 === lines[0].paragraphs.length) return;
191
+ const totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
189
192
  return this.selectionRange(-.1, totalCursorCount + .1), e.preventDefault(), !0;
190
193
  }
191
194
  return !1;
@@ -233,29 +236,32 @@ class RichTextEditPlugin {
233
236
  const {textConfig: textConfig, editOptions: editOptions} = this.currRt.attribute;
234
237
  if (textConfig && textConfig.length) return;
235
238
  if (!editOptions || !editOptions.placeholder) return;
236
- const {placeholder: placeholder, placeholderColor: placeholderColor = "rgba(0, 0, 0, 0.6)", placeholderFontFamily: placeholderFontFamily, placeholderFontSize: placeholderFontSize} = editOptions, shadow = this.currRt.shadowRoot || this.currRt.attachShadow();
237
- this.shadowPlaceHolder = (0, graphic_1.createRichText)(Object.assign(Object.assign({}, this.currRt.attribute), {
239
+ const {placeholder: placeholder, placeholderColor: placeholderColor = "rgba(0, 0, 0, 0.6)", placeholderFontFamily: placeholderFontFamily, placeholderFontSize: placeholderFontSize} = editOptions, shadow = this.getShadow(this.currRt), textConfigItem = Object.assign(Object.assign({}, (0,
240
+ edit_module_1.getDefaultCharacterConfig)(this.currRt.attribute)), {
241
+ text: placeholder
242
+ });
243
+ placeholderColor && (textConfigItem.fill = placeholderColor), placeholderFontFamily && (textConfigItem.fontFamily = placeholderFontFamily),
244
+ placeholderFontSize && (textConfigItem.fontSize = placeholderFontSize), this.shadowPlaceHolder = (0,
245
+ graphic_1.createRichText)(Object.assign(Object.assign({}, this.currRt.attribute), {
238
246
  x: 0,
239
247
  y: 0,
248
+ pickable: !1,
249
+ editable: !1,
250
+ editOptions: null,
240
251
  angle: 0,
241
252
  _debug_bounds: !1,
242
- textConfig: [ {
243
- text: placeholder,
244
- fill: placeholderColor,
245
- fontFamily: placeholderFontFamily,
246
- fontSize: placeholderFontSize
247
- } ]
253
+ textConfig: [ textConfigItem ]
248
254
  })), shadow.add(this.shadowPlaceHolder);
249
255
  }
250
256
  tryShowInputBounds() {
251
257
  if (!this.currRt || !this.focusing) return;
252
258
  const {editOptions: editOptions = {}} = this.currRt.attribute, {boundsStrokeWhenInput: boundsStrokeWhenInput} = editOptions;
253
259
  if (!editOptions || !boundsStrokeWhenInput) return;
254
- const {attribute: attribute} = this.currRt, b = this.currRt.AABBBounds;
255
- let h = b.height();
260
+ const {attribute: attribute} = this.currRt;
261
+ let b = this.currRt.AABBBounds, h = b.height();
256
262
  if (!attribute.textConfig.length && this.editLine) {
257
263
  const {points: points} = this.editLine.attribute;
258
- h = points[1].y - points[0].y;
264
+ h = points[1].y - points[0].y, b = (0, graphic_1.getRichTextBounds)(Object.assign({}, this.shadowPlaceHolder.attribute));
259
265
  }
260
266
  this.shadowBounds = this.shadowBounds || (0, graphic_1.createRect)({}), this.shadowBounds.setAttributes({
261
267
  x: 0,
@@ -265,16 +271,15 @@ class RichTextEditPlugin {
265
271
  fill: !1,
266
272
  stroke: boundsStrokeWhenInput,
267
273
  lineWidth: 1,
268
- boundsMode: "empty",
269
274
  zIndex: -1
270
275
  });
271
- (this.currRt.shadowRoot || this.currRt.attachShadow()).add(this.shadowBounds), this.offsetLineBgAndShadowBounds();
276
+ this.getShadow(this.currRt).add(this.shadowBounds), this.offsetLineBgAndShadowBounds();
272
277
  }
273
278
  trySyncPlaceholderToTextConfig() {
274
279
  if (!this.currRt) return;
275
280
  const {textConfig: textConfig, editOptions: editOptions} = this.currRt.attribute;
276
281
  if (textConfig && textConfig.length) return;
277
- if (!editOptions || !editOptions.placeholder) return;
282
+ if (!(editOptions && editOptions.placeholder && editOptions.syncPlaceHolderToTextConfig)) return;
278
283
  const {placeholder: placeholder} = editOptions;
279
284
  this.currRt.setAttributes({
280
285
  textConfig: [ Object.assign({
@@ -288,11 +293,12 @@ class RichTextEditPlugin {
288
293
  context.stage.off("dblclick", this.handleDBLClick), application_1.application.global.addEventListener("keydown", this.handleKeyDown);
289
294
  }
290
295
  onFocus(e, data) {
291
- this.deFocus(!1), this.focusing = !0;
296
+ this.updateCbs && this.updateCbs.forEach((cb => cb("beforeOnfocus", this))), this.deFocus(!1),
297
+ this.focusing = !0;
292
298
  const target = e.target;
293
299
  if (!target || "richtext" !== target.type) return;
294
300
  this.currRt = target, RichTextEditPlugin.tryUpdateRichtext(target);
295
- const shadowRoot = target.shadowRoot || target.attachShadow(), cache = target.getFrameCache();
301
+ const shadowRoot = this.getShadow(target), cache = target.getFrameCache();
296
302
  if (cache) {
297
303
  if (this.computeGlobalDelta(cache), shadowRoot.setAttributes({
298
304
  shadowRootIdx: 1,
@@ -304,16 +310,14 @@ class RichTextEditPlugin {
304
310
  x: 0,
305
311
  y: 0,
306
312
  lineWidth: 1,
307
- stroke: "black",
308
- boundsMode: "empty"
313
+ stroke: "black"
309
314
  });
310
315
  this.addAnimateToLine(line), this.editLine = line, this.ticker.start(!0);
311
316
  const g = (0, graphic_1.createGroup)({
312
317
  x: 0,
313
318
  y: 0,
314
319
  width: 0,
315
- height: 0,
316
- boundsMode: "empty"
320
+ height: 0
317
321
  });
318
322
  this.editBg = g, shadowRoot.add(this.editLine), shadowRoot.add(this.editBg);
319
323
  }
@@ -357,7 +361,9 @@ class RichTextEditPlugin {
357
361
  deFocus(trulyDeFocus = !1) {
358
362
  const target = this.currRt;
359
363
  if (!target) return;
360
- trulyDeFocus && (this.trySyncPlaceholderToTextConfig(), target.detachShadow());
364
+ this.updateCbs && this.updateCbs.forEach((cb => cb("beforeDefocus", this, {
365
+ trulyDeFocus: trulyDeFocus
366
+ }))), trulyDeFocus && (this.trySyncPlaceholderToTextConfig(), target.detachShadow());
361
367
  const currRt = this.currRt;
362
368
  this.currRt = null, this.editLine && (this.editLine.parent && this.editLine.parent.removeChild(this.editLine),
363
369
  this.editLine.release(), this.editLine = null, this.editBg.parent && this.editBg.parent.removeChild(this.editBg),
@@ -411,67 +417,75 @@ class RichTextEditPlugin {
411
417
  x: currCursorData.x,
412
418
  y: (currCursorData.y1 + currCursorData.y2) / 2
413
419
  }, line0Info = this.getLineByPoint(cache, startCursorPos), line1Info = this.getLineByPoint(cache, endCursorPos);
414
- if ((startCursorPos.y > endCursorPos.y || startCursorPos.y === endCursorPos.y && startCursorPos.x > endCursorPos.x) && ([startCursorPos, endCursorPos] = [ endCursorPos, startCursorPos ],
415
- [line1Info, line0Info] = [ line0Info, line1Info ]), this.hideSelection(), line0Info === line1Info) this.editBg.setAttributes({
416
- x: startCursorPos.x,
417
- y: line0Info.top,
418
- width: endCursorPos.x - startCursorPos.x,
419
- height: line0Info.height,
420
- fill: "#336df4",
421
- fillOpacity: .2
422
- }); else {
423
- this.editBg.setAttributes({
424
- x: 0,
420
+ if (line0Info && line1Info) {
421
+ if ((startCursorPos.y > endCursorPos.y || startCursorPos.y === endCursorPos.y && startCursorPos.x > endCursorPos.x) && ([startCursorPos, endCursorPos] = [ endCursorPos, startCursorPos ],
422
+ [line1Info, line0Info] = [ line0Info, line1Info ]), this.hideSelection(), line0Info === line1Info) this.editBg.setAttributes({
423
+ x: startCursorPos.x,
425
424
  y: line0Info.top,
426
- width: 0,
427
- height: 0
428
- });
429
- const startIdx = cache.lines.findIndex((item => item === line0Info)), endIdx = cache.lines.findIndex((item => item === line1Info));
430
- let y = 0;
431
- for (let i = startIdx; i <= endIdx; i++) {
432
- const line = cache.lines[i];
433
- if (i === startIdx) {
434
- const p = line.paragraphs[line.paragraphs.length - 1];
435
- this.editBg.add((0, graphic_1.createRect)({
436
- x: startCursorPos.x,
437
- y: y,
438
- width: p.left + p.width - startCursorPos.x,
439
- height: line.height,
440
- fill: "#336df4",
441
- fillOpacity: .2
442
- }));
443
- } else if (i === endIdx) {
444
- const p = line.paragraphs[0];
445
- this.editBg.add((0, graphic_1.createRect)({
446
- x: p.left,
447
- y: y,
448
- width: endCursorPos.x - p.left,
449
- height: line.height,
450
- fill: "#336df4",
451
- fillOpacity: .2
452
- }));
453
- } else {
454
- const p0 = line.paragraphs[0], p1 = line.paragraphs[line.paragraphs.length - 1];
455
- this.editBg.add((0, graphic_1.createRect)({
456
- x: p0.left,
457
- y: y,
458
- width: p1.left + p1.width - p0.left,
459
- height: line.height,
460
- fill: "#336df4",
461
- fillOpacity: .2
462
- }));
425
+ width: endCursorPos.x - startCursorPos.x,
426
+ height: line0Info.height,
427
+ fill: "#336df4",
428
+ fillOpacity: .2
429
+ }); else {
430
+ this.editBg.setAttributes({
431
+ x: 0,
432
+ y: line0Info.top,
433
+ width: 0,
434
+ height: 0
435
+ });
436
+ const startIdx = cache.lines.findIndex((item => item === line0Info)), endIdx = cache.lines.findIndex((item => item === line1Info));
437
+ let y = 0;
438
+ for (let i = startIdx; i <= endIdx; i++) {
439
+ const line = cache.lines[i];
440
+ if (i === startIdx) {
441
+ const p = line.paragraphs[line.paragraphs.length - 1];
442
+ this.editBg.add((0, graphic_1.createRect)({
443
+ x: startCursorPos.x,
444
+ y: y,
445
+ width: p.left + p.width - startCursorPos.x,
446
+ height: line.height,
447
+ fill: "#336df4",
448
+ fillOpacity: .2
449
+ }));
450
+ } else if (i === endIdx) {
451
+ const p = line.paragraphs[0];
452
+ this.editBg.add((0, graphic_1.createRect)({
453
+ x: p.left,
454
+ y: y,
455
+ width: endCursorPos.x - p.left,
456
+ height: line.height,
457
+ fill: "#336df4",
458
+ fillOpacity: .2
459
+ }));
460
+ } else {
461
+ const p0 = line.paragraphs[0], p1 = line.paragraphs[line.paragraphs.length - 1];
462
+ this.editBg.add((0, graphic_1.createRect)({
463
+ x: p0.left,
464
+ y: y,
465
+ width: p1.left + p1.width - p0.left,
466
+ height: line.height,
467
+ fill: "#336df4",
468
+ fillOpacity: .2
469
+ }));
470
+ }
471
+ y += line.height;
463
472
  }
464
- y += line.height;
465
473
  }
474
+ this.setCursorAndTextArea(currCursorData.x, currCursorData.y1, currCursorData.y2, this.currRt),
475
+ this.triggerRender(), this.updateCbs.forEach((cb => cb("selection", this)));
466
476
  }
467
- this.setCursorAndTextArea(currCursorData.x, currCursorData.y1, currCursorData.y2, this.currRt),
468
- this.triggerRender(), this.updateCbs.forEach((cb => cb("selection", this)));
469
477
  }
470
478
  hideSelection() {
471
479
  this.editBg && (this.editBg.removeAllChild(), this.editBg.setAttributes({
472
480
  fill: "transparent"
473
481
  }));
474
482
  }
483
+ getShadow(rt) {
484
+ const sr = rt.shadowRoot || rt.attachShadow();
485
+ return sr.setAttributes({
486
+ boundsMode: "empty"
487
+ }), sr;
488
+ }
475
489
  getLineByPoint(cache, p1) {
476
490
  let lineInfo = cache.lines[0];
477
491
  for (let i = 0; i < cache.lines.length && !(lineInfo.top <= p1.y && lineInfo.top + lineInfo.height >= p1.y); i++) lineInfo = cache.lines[i + 1];