@idraw/core 0.4.0-beta.3 → 0.4.0-beta.30

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 (63) hide show
  1. package/dist/esm/config.d.ts +1 -0
  2. package/dist/esm/config.js +1 -0
  3. package/dist/esm/index.d.ts +15 -5
  4. package/dist/esm/index.js +29 -8
  5. package/dist/esm/lib/cursor-image.d.ts +1 -0
  6. package/dist/esm/lib/cursor-image.js +1 -0
  7. package/dist/esm/lib/cursor.d.ts +3 -12
  8. package/dist/esm/lib/cursor.js +136 -112
  9. package/dist/esm/middleware/dragger/index.d.ts +2 -2
  10. package/dist/esm/middleware/dragger/index.js +1 -0
  11. package/dist/esm/middleware/info/draw-info.d.ts +31 -0
  12. package/dist/esm/middleware/info/draw-info.js +110 -0
  13. package/dist/esm/middleware/info/index.d.ts +3 -0
  14. package/dist/esm/middleware/info/index.js +110 -0
  15. package/dist/esm/middleware/info/types.d.ts +3 -0
  16. package/dist/esm/middleware/info/types.js +1 -0
  17. package/dist/esm/middleware/layout-selector/config.d.ts +9 -0
  18. package/dist/esm/middleware/layout-selector/config.js +9 -0
  19. package/dist/esm/middleware/layout-selector/index.d.ts +5 -0
  20. package/dist/esm/middleware/layout-selector/index.js +332 -0
  21. package/dist/esm/middleware/layout-selector/types.d.ts +15 -0
  22. package/dist/esm/middleware/layout-selector/types.js +2 -0
  23. package/dist/esm/middleware/layout-selector/util.d.ts +8 -0
  24. package/dist/esm/middleware/layout-selector/util.js +108 -0
  25. package/dist/esm/middleware/ruler/index.d.ts +3 -2
  26. package/dist/esm/middleware/ruler/index.js +12 -9
  27. package/dist/esm/middleware/ruler/types.d.ts +3 -0
  28. package/dist/esm/middleware/ruler/types.js +1 -0
  29. package/dist/esm/middleware/ruler/util.d.ts +15 -4
  30. package/dist/esm/middleware/ruler/util.js +81 -4
  31. package/dist/esm/middleware/scaler/index.d.ts +2 -2
  32. package/dist/esm/middleware/scaler/index.js +1 -0
  33. package/dist/esm/middleware/scroller/config.d.ts +2 -0
  34. package/dist/esm/middleware/scroller/config.js +2 -0
  35. package/dist/esm/middleware/scroller/index.d.ts +2 -1
  36. package/dist/esm/middleware/scroller/index.js +33 -5
  37. package/dist/esm/middleware/scroller/types.d.ts +11 -0
  38. package/dist/esm/middleware/scroller/types.js +1 -0
  39. package/dist/esm/middleware/scroller/util.d.ts +1 -1
  40. package/dist/esm/middleware/scroller/util.js +22 -17
  41. package/dist/esm/middleware/selector/config.d.ts +12 -0
  42. package/dist/esm/middleware/selector/config.js +12 -0
  43. package/dist/esm/middleware/selector/draw-auxiliary.d.ts +7 -0
  44. package/dist/esm/middleware/selector/draw-auxiliary.js +46 -0
  45. package/dist/esm/middleware/selector/draw-base.d.ts +30 -0
  46. package/dist/esm/middleware/selector/draw-base.js +100 -0
  47. package/dist/esm/middleware/selector/draw-reference.d.ts +5 -0
  48. package/dist/esm/middleware/selector/draw-reference.js +31 -0
  49. package/dist/esm/middleware/selector/draw-wrapper.d.ts +9 -1
  50. package/dist/esm/middleware/selector/draw-wrapper.js +34 -26
  51. package/dist/esm/middleware/selector/index.d.ts +7 -4
  52. package/dist/esm/middleware/selector/index.js +280 -45
  53. package/dist/esm/middleware/selector/reference.d.ts +13 -0
  54. package/dist/esm/middleware/selector/reference.js +267 -0
  55. package/dist/esm/middleware/selector/types.d.ts +9 -4
  56. package/dist/esm/middleware/selector/types.js +2 -1
  57. package/dist/esm/middleware/selector/util.d.ts +11 -2
  58. package/dist/esm/middleware/selector/util.js +36 -14
  59. package/dist/esm/middleware/text-editor/index.d.ts +20 -2
  60. package/dist/esm/middleware/text-editor/index.js +92 -16
  61. package/dist/index.global.js +3685 -953
  62. package/dist/index.global.min.js +1 -1
  63. package/package.json +5 -5
@@ -0,0 +1,267 @@
1
+ import { is } from '@idraw/util';
2
+ const unitSize = 2;
3
+ function getViewBoxInfo(rectInfo) {
4
+ const boxInfo = {
5
+ minX: rectInfo.topLeft.x,
6
+ minY: rectInfo.topLeft.y,
7
+ maxX: rectInfo.bottomRight.x,
8
+ maxY: rectInfo.bottomRight.y,
9
+ midX: rectInfo.center.x,
10
+ midY: rectInfo.center.y
11
+ };
12
+ return boxInfo;
13
+ }
14
+ const getClosestNumInSortedKeys = (sortedKeys, target) => {
15
+ if (sortedKeys.length === 0) {
16
+ throw null;
17
+ }
18
+ if (sortedKeys.length === 1) {
19
+ return sortedKeys[0];
20
+ }
21
+ let left = 0;
22
+ let right = sortedKeys.length - 1;
23
+ while (left <= right) {
24
+ const mid = Math.floor((left + right) / 2);
25
+ if (sortedKeys[mid] === target) {
26
+ return sortedKeys[mid];
27
+ }
28
+ else if (sortedKeys[mid] < target) {
29
+ left = mid + 1;
30
+ }
31
+ else {
32
+ right = mid - 1;
33
+ }
34
+ }
35
+ if (left >= sortedKeys.length) {
36
+ return sortedKeys[right];
37
+ }
38
+ if (right < 0) {
39
+ return sortedKeys[left];
40
+ }
41
+ return Math.abs(sortedKeys[right] - target) <= Math.abs(sortedKeys[left] - target) ? sortedKeys[right] : sortedKeys[left];
42
+ };
43
+ const isEqualNum = (a, b) => Math.abs(a - b) < 0.00001;
44
+ export function calcReferenceInfo(uuid, opts) {
45
+ var _a, _b;
46
+ const { data, groupQueue, calculator, viewScaleInfo, viewSizeInfo } = opts;
47
+ let targetElements = data.elements || [];
48
+ if ((groupQueue === null || groupQueue === void 0 ? void 0 : groupQueue.length) > 0) {
49
+ targetElements = ((_b = (_a = groupQueue[groupQueue.length - 1]) === null || _a === void 0 ? void 0 : _a.detail) === null || _b === void 0 ? void 0 : _b.children) || [];
50
+ }
51
+ const siblingViewRectInfoList = [];
52
+ targetElements.forEach((elem) => {
53
+ if (elem.uuid !== uuid) {
54
+ const info = calculator.calcViewRectInfoFromRange(elem.uuid, { checkVisible: true, viewScaleInfo, viewSizeInfo });
55
+ if (info) {
56
+ siblingViewRectInfoList.push(info);
57
+ }
58
+ }
59
+ });
60
+ const targetRectInfo = calculator.calcViewRectInfoFromRange(uuid, { viewScaleInfo, viewSizeInfo });
61
+ if (!targetRectInfo) {
62
+ return null;
63
+ }
64
+ const vTargetLineDotMap = {};
65
+ const hTargetLineDotMap = {};
66
+ const vRefLineDotMap = {};
67
+ const hRefLineDotMap = {};
68
+ const vHelperLineDotMapList = [];
69
+ const hHelperLineDotMapList = [];
70
+ let sortedRefXKeys = [];
71
+ let sortedRefYKeys = [];
72
+ const targetBox = getViewBoxInfo(targetRectInfo);
73
+ vTargetLineDotMap[targetBox.minX] = [targetBox.minY, targetBox.midY, targetBox.maxY];
74
+ vTargetLineDotMap[targetBox.midX] = [targetBox.minY, targetBox.midY, targetBox.maxY];
75
+ vTargetLineDotMap[targetBox.maxX] = [targetBox.minY, targetBox.midY, targetBox.maxY];
76
+ hTargetLineDotMap[targetBox.minY] = [targetBox.minX, targetBox.midX, targetBox.maxX];
77
+ hTargetLineDotMap[targetBox.midY] = [targetBox.minX, targetBox.midX, targetBox.maxX];
78
+ hTargetLineDotMap[targetBox.maxY] = [targetBox.minX, targetBox.midX, targetBox.maxX];
79
+ siblingViewRectInfoList.forEach((info) => {
80
+ const box = getViewBoxInfo(info);
81
+ if (!vRefLineDotMap[box.minX]) {
82
+ vRefLineDotMap[box.minX] = [];
83
+ }
84
+ if (!vRefLineDotMap[box.midX]) {
85
+ vRefLineDotMap[box.midX] = [];
86
+ }
87
+ if (!vRefLineDotMap[box.maxX]) {
88
+ vRefLineDotMap[box.maxX] = [];
89
+ }
90
+ if (!hRefLineDotMap[box.minY]) {
91
+ hRefLineDotMap[box.minY] = [];
92
+ }
93
+ if (!hRefLineDotMap[box.midY]) {
94
+ hRefLineDotMap[box.midY] = [];
95
+ }
96
+ if (!hRefLineDotMap[box.maxY]) {
97
+ hRefLineDotMap[box.maxY] = [];
98
+ }
99
+ vRefLineDotMap[box.minX] = [box.minY, box.midY, box.maxY];
100
+ vRefLineDotMap[box.midX] = [box.minY, box.midY, box.maxY];
101
+ vRefLineDotMap[box.maxX] = [box.minY, box.midY, box.maxY];
102
+ sortedRefXKeys.push(box.minX);
103
+ sortedRefXKeys.push(box.midX);
104
+ sortedRefXKeys.push(box.maxX);
105
+ hRefLineDotMap[box.minY] = [box.minX, box.midX, box.maxX];
106
+ hRefLineDotMap[box.midY] = [box.minX, box.midX, box.maxX];
107
+ hRefLineDotMap[box.maxY] = [box.minX, box.midX, box.maxX];
108
+ sortedRefYKeys.push(box.minY);
109
+ sortedRefYKeys.push(box.midY);
110
+ sortedRefYKeys.push(box.maxY);
111
+ });
112
+ sortedRefXKeys = sortedRefXKeys.sort((a, b) => a - b);
113
+ sortedRefYKeys = sortedRefYKeys.sort((a, b) => a - b);
114
+ let offsetX = null;
115
+ let offsetY = null;
116
+ let closestMinX = null;
117
+ let closestMidX = null;
118
+ let closestMaxX = null;
119
+ let closestMinY = null;
120
+ let closestMidY = null;
121
+ let closestMaxY = null;
122
+ if (sortedRefXKeys.length > 0) {
123
+ closestMinX = getClosestNumInSortedKeys(sortedRefXKeys, targetBox.minX);
124
+ closestMidX = getClosestNumInSortedKeys(sortedRefXKeys, targetBox.midX);
125
+ closestMaxX = getClosestNumInSortedKeys(sortedRefXKeys, targetBox.maxX);
126
+ const distMinX = Math.abs(closestMinX - targetBox.minX);
127
+ const distMidX = Math.abs(closestMidX - targetBox.midX);
128
+ const distMaxX = Math.abs(closestMaxX - targetBox.maxX);
129
+ const closestXDist = Math.min(distMinX, distMidX, distMaxX);
130
+ if (closestXDist <= unitSize / viewScaleInfo.scale) {
131
+ if (isEqualNum(closestXDist, distMinX)) {
132
+ offsetX = closestMinX - targetBox.minX;
133
+ }
134
+ else if (isEqualNum(closestXDist, distMidX)) {
135
+ offsetX = closestMidX - targetBox.midX;
136
+ }
137
+ else if (isEqualNum(closestXDist, distMaxX)) {
138
+ offsetX = closestMaxX - targetBox.maxX;
139
+ }
140
+ }
141
+ }
142
+ if (sortedRefYKeys.length > 0) {
143
+ closestMinY = getClosestNumInSortedKeys(sortedRefYKeys, targetBox.minY);
144
+ closestMidY = getClosestNumInSortedKeys(sortedRefYKeys, targetBox.midY);
145
+ closestMaxY = getClosestNumInSortedKeys(sortedRefYKeys, targetBox.maxY);
146
+ const distMinY = Math.abs(closestMinY - targetBox.minY);
147
+ const distMidY = Math.abs(closestMidY - targetBox.midY);
148
+ const distMaxY = Math.abs(closestMaxY - targetBox.maxY);
149
+ const closestYDist = Math.min(distMinY, distMidY, distMaxY);
150
+ if (closestYDist <= unitSize / viewScaleInfo.scale) {
151
+ if (isEqualNum(closestYDist, distMinY)) {
152
+ offsetY = closestMinY - targetBox.minY;
153
+ }
154
+ else if (isEqualNum(closestYDist, distMidY)) {
155
+ offsetY = closestMidY - targetBox.midY;
156
+ }
157
+ else if (isEqualNum(closestYDist, distMaxY)) {
158
+ offsetY = closestMaxY - targetBox.maxY;
159
+ }
160
+ }
161
+ }
162
+ const newTargetBox = Object.assign({}, targetBox);
163
+ if (offsetX !== null) {
164
+ newTargetBox.minX += offsetX;
165
+ newTargetBox.midX += offsetX;
166
+ newTargetBox.maxX += offsetX;
167
+ }
168
+ if (offsetY !== null) {
169
+ newTargetBox.minY += offsetY;
170
+ newTargetBox.midY += offsetY;
171
+ newTargetBox.maxY += offsetY;
172
+ }
173
+ if (is.x(offsetX) && offsetX !== null && closestMinX !== null && closestMidX !== null && closestMaxX !== null) {
174
+ if (isEqualNum(offsetX, closestMinX - targetBox.minX)) {
175
+ const vLine = {
176
+ x: closestMinX,
177
+ yList: []
178
+ };
179
+ vLine.yList.push(newTargetBox.minY);
180
+ vLine.yList.push(newTargetBox.maxY);
181
+ vLine.yList.push(...((hRefLineDotMap === null || hRefLineDotMap === void 0 ? void 0 : hRefLineDotMap[closestMinX]) || []));
182
+ vHelperLineDotMapList.push(vLine);
183
+ }
184
+ if (isEqualNum(offsetX, closestMidX - targetBox.minX)) {
185
+ const vLine = {
186
+ x: closestMidX,
187
+ yList: []
188
+ };
189
+ vLine.yList.push(newTargetBox.minY);
190
+ vLine.yList.push(newTargetBox.maxY);
191
+ vLine.yList.push(...((hRefLineDotMap === null || hRefLineDotMap === void 0 ? void 0 : hRefLineDotMap[closestMidX]) || []));
192
+ vHelperLineDotMapList.push(vLine);
193
+ }
194
+ if (isEqualNum(offsetX, closestMaxX - targetBox.minX)) {
195
+ const vLine = {
196
+ x: closestMaxX,
197
+ yList: []
198
+ };
199
+ vLine.yList.push(newTargetBox.minY);
200
+ vLine.yList.push(newTargetBox.maxY);
201
+ vLine.yList.push(...((hRefLineDotMap === null || hRefLineDotMap === void 0 ? void 0 : hRefLineDotMap[closestMaxX]) || []));
202
+ vHelperLineDotMapList.push(vLine);
203
+ }
204
+ }
205
+ if (is.y(offsetY) && offsetY !== null && closestMinY !== null && closestMidY !== null && closestMaxY !== null) {
206
+ if (isEqualNum(offsetY, closestMinY - targetBox.minY)) {
207
+ const hLine = {
208
+ y: closestMinY,
209
+ xList: []
210
+ };
211
+ hLine.xList.push(newTargetBox.minX);
212
+ hLine.xList.push(newTargetBox.maxX);
213
+ hLine.xList.push(...((vRefLineDotMap === null || vRefLineDotMap === void 0 ? void 0 : vRefLineDotMap[closestMinY]) || []));
214
+ hHelperLineDotMapList.push(hLine);
215
+ }
216
+ if (isEqualNum(offsetY, closestMidY - targetBox.midY)) {
217
+ const hLine = {
218
+ y: closestMidY,
219
+ xList: []
220
+ };
221
+ hLine.xList.push(newTargetBox.minX);
222
+ hLine.xList.push(newTargetBox.maxX);
223
+ hLine.xList.push(...((vRefLineDotMap === null || vRefLineDotMap === void 0 ? void 0 : vRefLineDotMap[closestMinY]) || []));
224
+ hHelperLineDotMapList.push(hLine);
225
+ }
226
+ if (isEqualNum(offsetY, closestMaxY - targetBox.maxY)) {
227
+ const hLine = {
228
+ y: closestMaxY,
229
+ xList: []
230
+ };
231
+ hLine.xList.push(newTargetBox.minX);
232
+ hLine.xList.push(newTargetBox.maxX);
233
+ hLine.xList.push(...((vRefLineDotMap === null || vRefLineDotMap === void 0 ? void 0 : vRefLineDotMap[closestMaxY]) || []));
234
+ hHelperLineDotMapList.push(hLine);
235
+ }
236
+ }
237
+ const yLines = [];
238
+ if ((vHelperLineDotMapList === null || vHelperLineDotMapList === void 0 ? void 0 : vHelperLineDotMapList.length) > 0) {
239
+ vHelperLineDotMapList.forEach((item, i) => {
240
+ yLines.push([]);
241
+ item.yList.forEach((y) => {
242
+ yLines[i].push({
243
+ x: item.x,
244
+ y
245
+ });
246
+ });
247
+ });
248
+ }
249
+ const xLines = [];
250
+ if ((hHelperLineDotMapList === null || hHelperLineDotMapList === void 0 ? void 0 : hHelperLineDotMapList.length) > 0) {
251
+ hHelperLineDotMapList.forEach((item, i) => {
252
+ xLines.push([]);
253
+ item.xList.forEach((x) => {
254
+ xLines[i].push({
255
+ x,
256
+ y: item.y
257
+ });
258
+ });
259
+ });
260
+ }
261
+ return {
262
+ offsetX,
263
+ offsetY,
264
+ yLines,
265
+ xLines
266
+ };
267
+ }
@@ -1,6 +1,6 @@
1
- import type { ElementSizeController } from '@idraw/types';
2
- import { keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyGroupQueueVertexesList, keyHoverElement, keyHoverElementVertexes, keySelectedElementList, keySelectedElementListVertexes, keySelectedElementController, keyDebugElemCenter, keyDebugEnd0, keyDebugEndHorizontal, keyDebugEndVertical, keyDebugStartHorizontal, keyDebugStartVertical } from './config';
3
- import { Data, ElementSize, ElementType, Element, ViewContext2D, Point, PointSize, ViewScaleInfo, ViewSizeInfo, ViewCalculator, PointWatcherEvent, BoardMiddleware, ViewRectVertexes } from '@idraw/types';
1
+ import { Data, ElementSize, ElementType, Element, ViewContext2D, Point, PointSize, ViewScaleInfo, ViewSizeInfo, ViewCalculator, PointWatcherEvent, BoardMiddleware, ViewRectVertexes, ElementSizeController, ElementPosition } from '@idraw/types';
2
+ import { keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyGroupQueueVertexesList, keyHoverElement, keyHoverElementVertexes, keySelectedElementList, keySelectedElementListVertexes, keySelectedElementController, keySelectedElementPosition, keyIsMoving, keyEnableSelectInGroup, keyEnableSnapToGrid, keyDebugElemCenter, keyDebugEnd0, keyDebugEndHorizontal, keyDebugEndVertical, keyDebugStartHorizontal, keyDebugStartVertical } from './config';
3
+ import { keyLayoutIsSelected } from '../layout-selector';
4
4
  export { Data, ElementType, Element, ElementSize, ViewContext2D, Point, PointSize, ViewScaleInfo, ViewSizeInfo, ViewCalculator, PointWatcherEvent, BoardMiddleware };
5
5
  export type ControllerStyle = ElementSize & {
6
6
  borderWidth: number;
@@ -8,7 +8,7 @@ export type ControllerStyle = ElementSize & {
8
8
  background: string;
9
9
  };
10
10
  export type SelectedElementSizeController = Record<string, ControllerStyle>;
11
- export type ResizeType = 'resize-left' | 'resize-right' | 'resize-top' | 'resize-bottom' | 'resize-top-left' | 'resize-top-right' | 'resize-bottom-left' | 'resize-bottom-right';
11
+ export type ResizeType = 'resize-left' | 'resize-right' | 'resize-top' | 'resize-bottom' | 'resize-top-left' | 'resize-top-right' | 'resize-bottom-left' | 'resize-bottom-right' | 'resize-rotate';
12
12
  export type PointTargetType = null | ResizeType | 'list-area' | 'over-element';
13
13
  export interface PointTarget {
14
14
  type: PointTargetType;
@@ -31,10 +31,15 @@ export type DeepSelectorSharedStorage = {
31
31
  [keySelectedElementList]: Array<Element<ElementType>>;
32
32
  [keySelectedElementListVertexes]: ViewRectVertexes | null;
33
33
  [keySelectedElementController]: ElementSizeController | null;
34
+ [keySelectedElementPosition]: ElementPosition;
35
+ [keyIsMoving]: boolean | null;
36
+ [keyEnableSelectInGroup]: boolean | null;
37
+ [keyEnableSnapToGrid]: boolean | null;
34
38
  [keyDebugElemCenter]: PointSize | null;
35
39
  [keyDebugEnd0]: PointSize | null;
36
40
  [keyDebugEndHorizontal]: PointSize | null;
37
41
  [keyDebugEndVertical]: PointSize | null;
38
42
  [keyDebugStartHorizontal]: PointSize | null;
39
43
  [keyDebugStartVertical]: PointSize | null;
44
+ [keyLayoutIsSelected]: boolean | null;
40
45
  };
@@ -1 +1,2 @@
1
- import { keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyGroupQueueVertexesList, keyHoverElement, keyHoverElementVertexes, keySelectedElementList, keySelectedElementListVertexes, keySelectedElementController, keyDebugElemCenter, keyDebugEnd0, keyDebugEndHorizontal, keyDebugEndVertical, keyDebugStartHorizontal, keyDebugStartVertical } from './config';
1
+ import { keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyGroupQueueVertexesList, keyHoverElement, keyHoverElementVertexes, keySelectedElementList, keySelectedElementListVertexes, keySelectedElementController, keySelectedElementPosition, keyIsMoving, keyEnableSelectInGroup, keyEnableSnapToGrid, keyDebugElemCenter, keyDebugEnd0, keyDebugEndHorizontal, keyDebugEndVertical, keyDebugStartHorizontal, keyDebugStartVertical } from './config';
2
+ import { keyLayoutIsSelected } from '../layout-selector';
@@ -1,5 +1,5 @@
1
- import type { ViewRectVertexes, ElementSizeController, StoreSharer } from '@idraw/types';
2
- import type { Data, Element, ViewContext2D, Point, PointSize, PointTarget, ViewScaleInfo, ViewCalculator, ElementType, ElementSize, ResizeType, AreaSize, ViewSizeInfo } from './types';
1
+ import type { ViewRectVertexes, ElementSizeController, StoreSharer, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
2
+ import type { Data, Element, ViewContext2D, Point, PointSize, PointTarget, ViewCalculator, ElementType, ElementSize, ResizeType, AreaSize } from './types';
3
3
  export declare function isPointInViewActiveVertexes(p: PointSize, opts: {
4
4
  ctx: ViewContext2D;
5
5
  vertexes: ViewRectVertexes;
@@ -30,6 +30,15 @@ export declare function resizeElement(elem: Element<ElementType>, opts: {
30
30
  scale: number;
31
31
  sharer: StoreSharer;
32
32
  }): ElementSize;
33
+ export declare function rotateElement(elem: Element<ElementType>, opts: {
34
+ center: PointSize;
35
+ start: PointSize;
36
+ end: PointSize;
37
+ resizeType: ResizeType;
38
+ viewScaleInfo: ViewScaleInfo;
39
+ viewSizeInfo: ViewSizeInfo;
40
+ sharer: StoreSharer;
41
+ }): ElementSize;
33
42
  export declare function getSelectedListArea(data: Data, opts: {
34
43
  start: Point;
35
44
  end: Point;
@@ -1,4 +1,4 @@
1
- import { calcElementCenter, rotateElementVertexes, calcElementVertexesInGroup, calcElementQueueVertexesQueueInGroup, calcViewPointSize, rotatePointInGroup, rotatePoint, parseAngleToRadian, limitAngle } from '@idraw/util';
1
+ import { calcElementCenter, rotateElementVertexes, calcElementVertexesInGroup, calcElementQueueVertexesQueueInGroup, calcViewPointSize, calcViewElementSize, rotatePointInGroup, rotatePoint, parseAngleToRadian, parseRadianToAngle, limitAngle, calcRadian } from '@idraw/util';
2
2
  function parseRadian(angle) {
3
3
  return (angle * Math.PI) / 180;
4
4
  }
@@ -9,11 +9,11 @@ function changeMoveDistDirect(moveDist, moveDirect) {
9
9
  return moveDirect > 0 ? Math.abs(moveDist) : 0 - Math.abs(moveDist);
10
10
  }
11
11
  export function isPointInViewActiveVertexes(p, opts) {
12
- const { ctx, viewScaleInfo, viewSizeInfo, vertexes } = opts;
13
- const v0 = calcViewPointSize(vertexes[0], { viewScaleInfo, viewSizeInfo });
14
- const v1 = calcViewPointSize(vertexes[1], { viewScaleInfo, viewSizeInfo });
15
- const v2 = calcViewPointSize(vertexes[2], { viewScaleInfo, viewSizeInfo });
16
- const v3 = calcViewPointSize(vertexes[3], { viewScaleInfo, viewSizeInfo });
12
+ const { ctx, viewScaleInfo, vertexes } = opts;
13
+ const v0 = calcViewPointSize(vertexes[0], { viewScaleInfo });
14
+ const v1 = calcViewPointSize(vertexes[1], { viewScaleInfo });
15
+ const v2 = calcViewPointSize(vertexes[2], { viewScaleInfo });
16
+ const v3 = calcViewPointSize(vertexes[3], { viewScaleInfo });
17
17
  ctx.beginPath();
18
18
  ctx.moveTo(v0.x, v0.y);
19
19
  ctx.lineTo(v1.x, v1.y);
@@ -49,8 +49,8 @@ export function getPointTarget(p, opts) {
49
49
  };
50
50
  const { ctx, data, calculator, selectedElements, viewScaleInfo, viewSizeInfo, areaSize, groupQueue, selectedElementController } = opts;
51
51
  if (selectedElementController) {
52
- const { left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight } = selectedElementController;
53
- const ctrls = [left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight];
52
+ const { left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, rotate } = selectedElementController;
53
+ const ctrls = [left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, rotate];
54
54
  for (let i = 0; i < ctrls.length; i++) {
55
55
  const ctrl = ctrls[i];
56
56
  if (isPointInViewActiveVertexes(p, { ctx, vertexes: ctrl.vertexes, viewSizeInfo, viewScaleInfo })) {
@@ -671,11 +671,29 @@ export function resizeElement(elem, opts) {
671
671
  }
672
672
  return { x, y, w, h, angle: elem.angle };
673
673
  }
674
+ export function rotateElement(elem, opts) {
675
+ const { x, y, w, h, angle = 0 } = elem;
676
+ const { center, start, end, viewScaleInfo } = opts;
677
+ const elemCenter = calcViewPointSize(center, {
678
+ viewScaleInfo
679
+ });
680
+ const startAngle = limitAngle(angle);
681
+ const changedRadian = calcRadian(elemCenter, start, end);
682
+ const endAngle = startAngle + parseRadianToAngle(changedRadian);
683
+ return {
684
+ x,
685
+ y,
686
+ w,
687
+ h,
688
+ angle: endAngle
689
+ };
690
+ }
674
691
  export function getSelectedListArea(data, opts) {
692
+ var _a;
675
693
  const indexes = [];
676
694
  const uuids = [];
677
695
  const elements = [];
678
- const { calculator, viewScaleInfo, viewSizeInfo, start, end } = opts;
696
+ const { viewScaleInfo, viewSizeInfo, start, end } = opts;
679
697
  if (!(Array.isArray(data.elements) && start && end)) {
680
698
  return { indexes, uuids, elements };
681
699
  }
@@ -683,8 +701,12 @@ export function getSelectedListArea(data, opts) {
683
701
  const endX = Math.max(start.x, end.x);
684
702
  const startY = Math.min(start.y, end.y);
685
703
  const endY = Math.max(start.y, end.y);
686
- data.elements.forEach((elem, idx) => {
687
- const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
704
+ for (let idx = 0; idx < data.elements.length; idx++) {
705
+ const elem = data.elements[idx];
706
+ if (((_a = elem === null || elem === void 0 ? void 0 : elem.operations) === null || _a === void 0 ? void 0 : _a.lock) === true) {
707
+ continue;
708
+ }
709
+ const elemSize = calcViewElementSize(elem, { viewScaleInfo, viewSizeInfo });
688
710
  const center = calcElementCenter(elemSize);
689
711
  if (center.x >= startX && center.x <= endX && center.y >= startY && center.y <= endY) {
690
712
  indexes.push(idx);
@@ -702,7 +724,7 @@ export function getSelectedListArea(data, opts) {
702
724
  }
703
725
  }
704
726
  }
705
- });
727
+ }
706
728
  return { indexes, uuids, elements };
707
729
  }
708
730
  export function calcSelectedElementsArea(elements, opts) {
@@ -711,14 +733,14 @@ export function calcSelectedElementsArea(elements, opts) {
711
733
  return null;
712
734
  }
713
735
  const area = { x: 0, y: 0, w: 0, h: 0 };
714
- const { calculator, viewScaleInfo, viewSizeInfo } = opts;
736
+ const { viewScaleInfo, viewSizeInfo } = opts;
715
737
  let prevElemSize = null;
716
738
  for (let i = 0; i < elements.length; i++) {
717
739
  const elem = elements[i];
718
740
  if ((_a = elem === null || elem === void 0 ? void 0 : elem.operations) === null || _a === void 0 ? void 0 : _a.invisible) {
719
741
  continue;
720
742
  }
721
- const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
743
+ const elemSize = calcViewElementSize(elem, { viewScaleInfo, viewSizeInfo });
722
744
  if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) {
723
745
  const ves = rotateElementVertexes(elemSize);
724
746
  if (ves.length === 4) {
@@ -1,3 +1,21 @@
1
- import type { BoardMiddleware, CoreEvent } from '@idraw/types';
1
+ import type { BoardMiddleware, CoreEventMap, Element, ViewScaleInfo, ElementPosition } from '@idraw/types';
2
2
  export declare const middlewareEventTextEdit = "@middleware/text-edit";
3
- export declare const MiddlewareTextEditor: BoardMiddleware<Record<string, any>, CoreEvent>;
3
+ export declare const middlewareEventTextChange = "@middleware/text-change";
4
+ type TextEditEvent = {
5
+ element: Element<'text'>;
6
+ position: ElementPosition;
7
+ groupQueue: Element<'group'>[];
8
+ viewScaleInfo: ViewScaleInfo;
9
+ };
10
+ type TextChangeEvent = {
11
+ element: {
12
+ uuid: string;
13
+ detail: {
14
+ text: string;
15
+ };
16
+ };
17
+ position: ElementPosition;
18
+ };
19
+ type ExtendEventMap = Record<typeof middlewareEventTextEdit, TextEditEvent> & Record<typeof middlewareEventTextChange, TextChangeEvent>;
20
+ export declare const MiddlewareTextEditor: BoardMiddleware<ExtendEventMap, CoreEventMap & ExtendEventMap>;
21
+ export {};
@@ -1,14 +1,17 @@
1
- import { limitAngle, getDefaultElementDetailConfig } from '@idraw/util';
1
+ import { limitAngle, getDefaultElementDetailConfig, enhanceFontFamliy } from '@idraw/util';
2
2
  export const middlewareEventTextEdit = '@middleware/text-edit';
3
+ export const middlewareEventTextChange = '@middleware/text-change';
3
4
  const defaultElementDetail = getDefaultElementDetailConfig();
4
5
  export const MiddlewareTextEditor = (opts) => {
5
- const { eventHub, boardContent, viewer } = opts;
6
+ const { eventHub, boardContent, viewer, sharer } = opts;
6
7
  const canvas = boardContent.boardContext.canvas;
7
- const textarea = document.createElement('textarea');
8
+ const textarea = document.createElement('div');
9
+ textarea.setAttribute('contenteditable', 'true');
8
10
  const canvasWrapper = document.createElement('div');
9
11
  const container = opts.container || document.body;
10
12
  const mask = document.createElement('div');
11
13
  let activeElem = null;
14
+ let activePosition = [];
12
15
  canvasWrapper.appendChild(textarea);
13
16
  canvasWrapper.style.position = 'absolute';
14
17
  mask.appendChild(canvasWrapper);
@@ -23,10 +26,27 @@ export const MiddlewareTextEditor = (opts) => {
23
26
  resetCanvasWrapper();
24
27
  resetTextArea(e);
25
28
  mask.style.display = 'block';
29
+ if (activeElem === null || activeElem === void 0 ? void 0 : activeElem.uuid) {
30
+ sharer.setActiveOverrideElemenentMap({
31
+ [activeElem.uuid]: {
32
+ operations: { invisible: true }
33
+ }
34
+ });
35
+ viewer.drawFrame();
36
+ }
26
37
  };
27
38
  const hideTextArea = () => {
39
+ if (activeElem === null || activeElem === void 0 ? void 0 : activeElem.uuid) {
40
+ const map = sharer.getActiveOverrideElemenentMap();
41
+ if (map) {
42
+ delete map[activeElem.uuid];
43
+ }
44
+ sharer.setActiveOverrideElemenentMap(map);
45
+ viewer.drawFrame();
46
+ }
28
47
  mask.style.display = 'none';
29
48
  activeElem = null;
49
+ activePosition = [];
30
50
  };
31
51
  const getCanvasRect = () => {
32
52
  const clientRect = canvas.getBoundingClientRect();
@@ -84,24 +104,45 @@ export const MiddlewareTextEditor = (opts) => {
84
104
  elemW = element.w * scale;
85
105
  elemH = element.h * scale;
86
106
  }
107
+ let justifyContent = 'center';
108
+ let alignItems = 'center';
109
+ if (detail.textAlign === 'left') {
110
+ justifyContent = 'start';
111
+ }
112
+ else if (detail.textAlign === 'right') {
113
+ justifyContent = 'end';
114
+ }
115
+ if (detail.verticalAlign === 'top') {
116
+ alignItems = 'start';
117
+ }
118
+ else if (detail.verticalAlign === 'bottom') {
119
+ alignItems = 'end';
120
+ }
121
+ textarea.style.display = 'inline-flex';
122
+ textarea.style.justifyContent = justifyContent;
123
+ textarea.style.alignItems = alignItems;
87
124
  textarea.style.position = 'absolute';
88
- textarea.style.left = `${elemX}px`;
89
- textarea.style.top = `${elemY}px`;
90
- textarea.style.width = `${elemW}px`;
91
- textarea.style.height = `${elemH}px`;
125
+ textarea.style.left = `${elemX - 1}px`;
126
+ textarea.style.top = `${elemY - 1}px`;
127
+ textarea.style.width = `${elemW + 2}px`;
128
+ textarea.style.height = `${elemH + 2}px`;
92
129
  textarea.style.transform = `rotate(${limitAngle(element.angle || 0)}deg)`;
93
130
  textarea.style.boxSizing = 'border-box';
94
131
  textarea.style.border = '1px solid #1973ba';
95
132
  textarea.style.resize = 'none';
96
133
  textarea.style.overflow = 'hidden';
97
134
  textarea.style.wordBreak = 'break-all';
98
- textarea.style.background = '#FFFFFF';
99
- textarea.style.color = '#333333';
135
+ textarea.style.borderRadius = `${(typeof detail.borderRadius === 'number' ? detail.borderRadius : 0) * scale}px`;
136
+ textarea.style.background = `${detail.background || 'transparent'}`;
137
+ textarea.style.color = `${detail.color || '#333333'}`;
100
138
  textarea.style.fontSize = `${detail.fontSize * scale}px`;
101
- textarea.style.lineHeight = `${detail.lineHeight * scale}px`;
102
- textarea.style.fontFamily = detail.fontFamily;
139
+ textarea.style.lineHeight = `${(detail.lineHeight || detail.fontSize) * scale}px`;
140
+ textarea.style.fontFamily = enhanceFontFamliy(detail.fontFamily);
103
141
  textarea.style.fontWeight = `${detail.fontWeight}`;
104
- textarea.value = detail.text || '';
142
+ textarea.style.padding = '0';
143
+ textarea.style.margin = '0';
144
+ textarea.style.outline = 'none';
145
+ textarea.innerText = detail.text || '';
105
146
  parent.appendChild(textarea);
106
147
  };
107
148
  const resetCanvasWrapper = () => {
@@ -119,23 +160,58 @@ export const MiddlewareTextEditor = (opts) => {
119
160
  textarea.addEventListener('click', (e) => {
120
161
  e.stopPropagation();
121
162
  });
122
- textarea.addEventListener('input', (e) => {
123
- if (activeElem) {
124
- activeElem.detail.text = e.target.value || '';
163
+ textarea.addEventListener('input', () => {
164
+ if (activeElem && activePosition) {
165
+ activeElem.detail.text = textarea.innerText || '';
166
+ eventHub.trigger(middlewareEventTextChange, {
167
+ element: {
168
+ uuid: activeElem.uuid,
169
+ detail: {
170
+ text: activeElem.detail.text
171
+ }
172
+ },
173
+ position: [...(activePosition || [])]
174
+ });
125
175
  viewer.drawFrame();
126
176
  }
127
177
  });
128
178
  textarea.addEventListener('blur', () => {
179
+ if (activeElem && activePosition) {
180
+ eventHub.trigger(middlewareEventTextChange, {
181
+ element: {
182
+ uuid: activeElem.uuid,
183
+ detail: {
184
+ text: activeElem.detail.text
185
+ }
186
+ },
187
+ position: [...activePosition]
188
+ });
189
+ }
129
190
  hideTextArea();
130
191
  });
192
+ textarea.addEventListener('keydown', (e) => {
193
+ e.stopPropagation();
194
+ });
195
+ textarea.addEventListener('keypress', (e) => {
196
+ e.stopPropagation();
197
+ });
198
+ textarea.addEventListener('keyup', (e) => {
199
+ e.stopPropagation();
200
+ });
201
+ textarea.addEventListener('wheel', (e) => {
202
+ e.stopPropagation();
203
+ e.preventDefault();
204
+ });
131
205
  const textEditCallback = (e) => {
132
206
  var _a;
133
- if ((e === null || e === void 0 ? void 0 : e.element) && ((_a = e === null || e === void 0 ? void 0 : e.element) === null || _a === void 0 ? void 0 : _a.type) === 'text') {
207
+ if ((e === null || e === void 0 ? void 0 : e.position) && (e === null || e === void 0 ? void 0 : e.element) && ((_a = e === null || e === void 0 ? void 0 : e.element) === null || _a === void 0 ? void 0 : _a.type) === 'text') {
134
208
  activeElem = e.element;
209
+ activePosition = e.position;
135
210
  }
136
211
  showTextArea(e);
137
212
  };
138
213
  return {
214
+ name: '@middleware/text-editor',
139
215
  use() {
140
216
  eventHub.on(middlewareEventTextEdit, textEditCallback);
141
217
  },