@archireport/react-native-svg-draw 2.2.0 → 2.3.0

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 (59) hide show
  1. package/lib/commonjs/components/DrawCore/CurrentAnimatedItem.js +284 -29
  2. package/lib/commonjs/components/DrawCore/CurrentAnimatedItem.js.map +1 -1
  3. package/lib/commonjs/components/DrawCore/CurrentAnimatedText.js +12 -11
  4. package/lib/commonjs/components/DrawCore/CurrentAnimatedText.js.map +1 -1
  5. package/lib/commonjs/components/DrawCore/DrawContext.js.map +1 -1
  6. package/lib/commonjs/components/DrawCore/DrawPad.js +21 -7
  7. package/lib/commonjs/components/DrawCore/DrawPad.js.map +1 -1
  8. package/lib/commonjs/components/DrawCore/DrawProvider.js +6 -2
  9. package/lib/commonjs/components/DrawCore/DrawProvider.js.map +1 -1
  10. package/lib/commonjs/components/DrawCore/Item.js +154 -7
  11. package/lib/commonjs/components/DrawCore/Item.js.map +1 -1
  12. package/lib/commonjs/components/DrawCore/index.js +175 -83
  13. package/lib/commonjs/components/DrawCore/index.js.map +1 -1
  14. package/lib/commonjs/components/DrawCore/useDrawHook.js +4 -2
  15. package/lib/commonjs/components/DrawCore/useDrawHook.js.map +1 -1
  16. package/lib/commonjs/components/DrawWithOptions/index.js +14 -0
  17. package/lib/commonjs/components/DrawWithOptions/index.js.map +1 -1
  18. package/lib/module/components/DrawCore/CurrentAnimatedItem.js +286 -31
  19. package/lib/module/components/DrawCore/CurrentAnimatedItem.js.map +1 -1
  20. package/lib/module/components/DrawCore/CurrentAnimatedText.js +12 -11
  21. package/lib/module/components/DrawCore/CurrentAnimatedText.js.map +1 -1
  22. package/lib/module/components/DrawCore/DrawContext.js.map +1 -1
  23. package/lib/module/components/DrawCore/DrawPad.js +21 -7
  24. package/lib/module/components/DrawCore/DrawPad.js.map +1 -1
  25. package/lib/module/components/DrawCore/DrawProvider.js +6 -2
  26. package/lib/module/components/DrawCore/DrawProvider.js.map +1 -1
  27. package/lib/module/components/DrawCore/Item.js +150 -9
  28. package/lib/module/components/DrawCore/Item.js.map +1 -1
  29. package/lib/module/components/DrawCore/index.js +176 -84
  30. package/lib/module/components/DrawCore/index.js.map +1 -1
  31. package/lib/module/components/DrawCore/useDrawHook.js +4 -2
  32. package/lib/module/components/DrawCore/useDrawHook.js.map +1 -1
  33. package/lib/module/components/DrawWithOptions/index.js +14 -0
  34. package/lib/module/components/DrawWithOptions/index.js.map +1 -1
  35. package/lib/typescript/components/DrawCore/CurrentAnimatedItem.d.ts +3 -5
  36. package/lib/typescript/components/DrawCore/CurrentAnimatedItem.d.ts.map +1 -1
  37. package/lib/typescript/components/DrawCore/CurrentAnimatedText.d.ts.map +1 -1
  38. package/lib/typescript/components/DrawCore/DrawContext.d.ts +2 -0
  39. package/lib/typescript/components/DrawCore/DrawContext.d.ts.map +1 -1
  40. package/lib/typescript/components/DrawCore/DrawPad.d.ts +2 -1
  41. package/lib/typescript/components/DrawCore/DrawPad.d.ts.map +1 -1
  42. package/lib/typescript/components/DrawCore/DrawProvider.d.ts.map +1 -1
  43. package/lib/typescript/components/DrawCore/Item.d.ts +27 -0
  44. package/lib/typescript/components/DrawCore/Item.d.ts.map +1 -1
  45. package/lib/typescript/components/DrawCore/index.d.ts.map +1 -1
  46. package/lib/typescript/components/DrawCore/useDrawHook.d.ts +1 -0
  47. package/lib/typescript/components/DrawCore/useDrawHook.d.ts.map +1 -1
  48. package/lib/typescript/components/DrawWithOptions/index.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/components/DrawCore/CurrentAnimatedItem.tsx +307 -7
  51. package/src/components/DrawCore/CurrentAnimatedText.tsx +5 -2
  52. package/src/components/DrawCore/DrawContext.tsx +2 -0
  53. package/src/components/DrawCore/DrawPad.tsx +20 -4
  54. package/src/components/DrawCore/DrawProvider.tsx +6 -0
  55. package/src/components/DrawCore/Item.tsx +188 -7
  56. package/src/components/DrawCore/index.tsx +243 -120
  57. package/src/components/DrawCore/useDrawHook.tsx +2 -0
  58. package/src/components/DrawWithOptions/index.tsx +18 -0
  59. package/src/types.d.ts +7 -0
@@ -2,10 +2,16 @@ import React from 'react';
2
2
  import Animated, {
3
3
  createAnimatedPropAdapter,
4
4
  processColor,
5
+ runOnJS,
5
6
  useAnimatedProps,
7
+ useAnimatedReaction,
6
8
  } from 'react-native-reanimated';
7
9
  import { Path, Ellipse, Rect, Line, G } from 'react-native-svg';
8
- import type { DrawItem, hslColor, Point } from '../../types';
10
+ import type { hslColor, Point } from '../../types';
11
+ import { TextInput } from 'react-native';
12
+ import useDrawHook from './useDrawHook';
13
+
14
+ //import { TextInput } from 'react-native-gesture-handler';
9
15
 
10
16
  const AnimatedPath = Animated.createAnimatedComponent(Path);
11
17
 
@@ -15,6 +21,10 @@ const AnimatedRectangle = Animated.createAnimatedComponent(Rect);
15
21
 
16
22
  const AnimatedLine = Animated.createAnimatedComponent(Line);
17
23
 
24
+ //const AnimatedText = Animated.createAnimatedComponent(Text);
25
+
26
+ const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
27
+
18
28
  // properties of a line
19
29
  const line = (pointA: Point, pointB: Point) => {
20
30
  'worklet';
@@ -109,7 +119,7 @@ function hue2rgb(p: number, q: number, t: number) {
109
119
  }
110
120
 
111
121
  // see https://github.com/software-mansion/react-native-reanimated/issues/1909
112
- function hslToRgb(col: hslColor) {
122
+ export function hslToRgb(col: hslColor) {
113
123
  'worklet';
114
124
  const hslRegExp = new RegExp(/hsl\(([\d.]+),\s*(\d+)%,\s*([\d.]+)%\)/);
115
125
  const res = hslRegExp.exec(col);
@@ -153,11 +163,18 @@ const propAdapter = createAnimatedPropAdapter(
153
163
  ['fill', 'stroke']
154
164
  );
155
165
 
156
- export default function CurrentAnimatedItem({
157
- currentItem,
158
- }: {
159
- currentItem: Animated.SharedValue<DrawItem | null>;
160
- }) {
166
+ export default function CurrentAnimatedItem() {
167
+ const { currentItem, doubleArrowTextInput } = useDrawHook();
168
+
169
+ const getTextLength = () => {
170
+ 'worklet';
171
+ const text =
172
+ currentItem.value?.type === 'doubleArrows' ? currentItem.value?.text : '';
173
+
174
+ const textLength = text && text.length > 5 ? text.length * 10 : 50;
175
+ return textLength;
176
+ };
177
+
161
178
  const ellipseAnimatedProps = useAnimatedProps(
162
179
  () => {
163
180
  const coordinates =
@@ -235,6 +252,237 @@ export default function CurrentAnimatedItem({
235
252
  null,
236
253
  propAdapter
237
254
  );
255
+ const distance = (x1: number, y1: number, x2: number, y2: number) => {
256
+ 'worklet';
257
+ return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
258
+ };
259
+
260
+ const getCoordinatesWithRatio = ({
261
+ c1,
262
+ c2,
263
+ ratio,
264
+ first = true,
265
+ }: {
266
+ c1: number;
267
+ c2: number;
268
+ ratio: number;
269
+ first?: boolean;
270
+ }): [number, number] => {
271
+ 'worklet';
272
+ let newC1 = c1;
273
+ let newC2 = c2;
274
+
275
+ if (c1 > c2) {
276
+ if (first) {
277
+ newC1 = c1;
278
+ newC2 = c1 - (c1 - c2) * ratio;
279
+ } else {
280
+ newC1 = c2 + (c1 - c2) * ratio;
281
+ newC2 = c2;
282
+ }
283
+ } else {
284
+ if (first) {
285
+ newC1 = c1;
286
+ newC2 = c1 + (c2 - c1) * ratio;
287
+ } else {
288
+ newC1 = c2 - (c2 - c1) * ratio;
289
+ newC2 = c2;
290
+ }
291
+ }
292
+
293
+ return [newC1 as number, newC2 as number];
294
+ };
295
+
296
+ const getGetcoordinateValue = ({
297
+ x1,
298
+ y1,
299
+ x2,
300
+ y2,
301
+ first = true,
302
+ }: {
303
+ x1: number;
304
+ y1: number;
305
+ x2: number;
306
+ y2: number;
307
+ first: boolean;
308
+ }) => {
309
+ 'worklet';
310
+ //console.log('*******************');
311
+ const dist = distance(x1, y1, x2, y2);
312
+ const textLength = getTextLength();
313
+ const newDist = (!textLength ? dist : dist - textLength) / 2;
314
+
315
+ let newX1 = x1;
316
+ let newY1 = y1;
317
+ let newX2 = x2;
318
+ let newY2 = y2;
319
+
320
+ //if (newDist > textLength / 2 && !isShortArrow) {
321
+ const ratio = newDist / dist;
322
+ [newX1, newX2] = getCoordinatesWithRatio({
323
+ c1: x1,
324
+ c2: x2,
325
+ ratio,
326
+ first,
327
+ });
328
+ [newY1, newY2] = getCoordinatesWithRatio({
329
+ c1: y1,
330
+ c2: y2,
331
+ ratio,
332
+ first,
333
+ });
334
+ //}
335
+ return [newX1, newY1, newX2, newY2];
336
+ };
337
+
338
+ const doubleArrowsAnimatedPropsFirst = useAnimatedProps(
339
+ () => {
340
+ let x1, y1, x2, y2;
341
+
342
+ if (currentItem.value?.type !== 'doubleArrows') {
343
+ x1 = -10;
344
+ y1 = -10;
345
+ x2 = -10;
346
+ y2 = -10;
347
+ } else {
348
+ const coordinates = currentItem.value.data;
349
+ [x1, y1, x2, y2] = getGetcoordinateValue({
350
+ x1: Number(coordinates.x1),
351
+ y1: Number(coordinates.y1),
352
+ x2: Number(coordinates.x2),
353
+ y2: Number(coordinates.y2),
354
+ first: true,
355
+ //text: currentItem.value?.text,
356
+ });
357
+ }
358
+
359
+ return {
360
+ x1,
361
+ y1,
362
+ x2,
363
+ y2,
364
+ fill: 'transparent',
365
+ stroke: hslToRgb(currentItem.value?.color || 'hsl(0, 0%, 0%)'),
366
+ opacity: currentItem.value?.type === 'doubleArrows' ? 1 : 0,
367
+ strokeWidth:
368
+ currentItem.value?.type === 'doubleArrows'
369
+ ? currentItem.value.strokeWidth
370
+ : 0,
371
+ markerStart: 'arrowheadStart',
372
+ };
373
+ },
374
+ null,
375
+ propAdapter
376
+ );
377
+
378
+ const doubleArrowsAnimatedPropsLast = useAnimatedProps(
379
+ () => {
380
+ let x1, y1, x2, y2;
381
+
382
+ if (currentItem.value?.type !== 'doubleArrows') {
383
+ x1 = -10;
384
+ y1 = -10;
385
+ x2 = -10;
386
+ y2 = -10;
387
+ } else {
388
+ const coordinates = currentItem.value.data;
389
+ [x1, y1, x2, y2] = getGetcoordinateValue({
390
+ x1: Number(coordinates.x1),
391
+ y1: Number(coordinates.y1),
392
+ x2: Number(coordinates.x2),
393
+ y2: Number(coordinates.y2),
394
+ first: false,
395
+ //text: currentItem.value?.text,
396
+ });
397
+ }
398
+
399
+ return {
400
+ x1,
401
+ y1,
402
+ x2,
403
+ y2,
404
+ fill: 'transparent',
405
+ stroke: hslToRgb(currentItem.value?.color || 'hsl(0, 0%, 0%)'),
406
+ opacity: currentItem.value?.type === 'doubleArrows' ? 1 : 0,
407
+ strokeWidth:
408
+ currentItem.value?.type === 'doubleArrows'
409
+ ? currentItem.value.strokeWidth
410
+ : 0,
411
+ markerEnd: 'arrowhead',
412
+ };
413
+ },
414
+ null,
415
+ propAdapter
416
+ );
417
+
418
+ const getTextValues = ({
419
+ x1,
420
+ y1,
421
+ x2,
422
+ y2,
423
+ }: {
424
+ x1: number;
425
+ y1: number;
426
+ x2: number;
427
+ y2: number;
428
+ }): [number, number, number] => {
429
+ 'worklet';
430
+ const dist = distance(x1, y1, x2, y2);
431
+ const ratio = 0.5;
432
+ const newX = (x1 + x2) * ratio;
433
+ const newY = (y1 + y2) * ratio;
434
+
435
+ let angle = 0;
436
+ if (x1 > x2) {
437
+ if (y1 > y2) {
438
+ angle = Math.acos((x1 - x2) / dist) * (180 / Math.PI);
439
+ } else {
440
+ angle = 180 - Math.acos((x1 - x2) / dist) * (180 / Math.PI) + 180;
441
+ }
442
+ } else {
443
+ if (y1 > y2) {
444
+ angle = 180 - Math.acos((x2 - x1) / dist) * (180 / Math.PI) + 180;
445
+ } else {
446
+ angle = Math.acos((x2 - x1) / dist) * (180 / Math.PI);
447
+ }
448
+ }
449
+
450
+ return [newX, newY, angle];
451
+ };
452
+ const doubleArrowsAnimatedPropsText = useAnimatedProps(
453
+ () => {
454
+ let x = 0,
455
+ y = 0,
456
+ angle = 0;
457
+
458
+ if (currentItem.value?.type !== 'doubleArrows') {
459
+ x = -50;
460
+ y = -50;
461
+ angle = 0;
462
+ } else {
463
+ const coordinates = currentItem.value.data;
464
+ [x, y, angle] = getTextValues({
465
+ x1: Number(coordinates.x1),
466
+ y1: Number(coordinates.y1),
467
+ x2: Number(coordinates.x2),
468
+ y2: Number(coordinates.y2),
469
+ });
470
+ }
471
+
472
+ return {
473
+ top: y - 10,
474
+ left: x - getTextLength() / 2,
475
+ fontSize: 10 + (currentItem.value?.strokeWidth ?? 0) * 2,
476
+ color: currentItem.value?.color
477
+ ? hslToRgb(currentItem.value?.color)
478
+ : 'white',
479
+ transform: [{ rotateZ: `${angle}deg` }],
480
+ width: getTextLength(),
481
+ };
482
+ },
483
+ null,
484
+ propAdapter
485
+ );
238
486
 
239
487
  const rectangleAnimatedProps = useAnimatedProps(
240
488
  () => {
@@ -284,6 +532,24 @@ export default function CurrentAnimatedItem({
284
532
  propAdapter
285
533
  );
286
534
 
535
+ const updateText = (value: string) => {
536
+ if (!doubleArrowTextInput?.current) return;
537
+ doubleArrowTextInput.current.setNativeProps({
538
+ text: value,
539
+ });
540
+ };
541
+ useAnimatedReaction(
542
+ () => {
543
+ return currentItem.value?.type === 'doubleArrows'
544
+ ? currentItem.value?.text || ''
545
+ : '';
546
+ },
547
+ (value) => {
548
+ if (updateText) runOnJS(updateText)(value);
549
+ },
550
+ [updateText, doubleArrowTextInput]
551
+ );
552
+
287
553
  return (
288
554
  <>
289
555
  <AnimatedEllipse animatedProps={ellipseAnimatedProps} />
@@ -293,6 +559,40 @@ export default function CurrentAnimatedItem({
293
559
  <G markerStart="url(#selection)" markerEnd="url(#selection)">
294
560
  <AnimatedLine animatedProps={doubleHeadAnimatedProps} />
295
561
  </G>
562
+ <G markerStart="url(#selection)" markerEnd="url(#selection)">
563
+ <AnimatedLine animatedProps={doubleArrowsAnimatedPropsFirst} />
564
+
565
+ <AnimatedTextInput
566
+ animatedProps={{
567
+ ...(doubleArrowsAnimatedPropsText as any), // Type cast to bypass the type error
568
+ // Ensure other relevant props if needed
569
+ }}
570
+ value={
571
+ currentItem.value?.type === 'doubleArrows'
572
+ ? currentItem.value.text
573
+ : ''
574
+ }
575
+ ref={doubleArrowTextInput}
576
+ underlineColorAndroid={'transparent'}
577
+ onChangeText={(text) => {
578
+ console.log('onChangeText', text);
579
+ if (currentItem.value?.type === 'doubleArrows') {
580
+ currentItem.value = {
581
+ ...currentItem.value,
582
+ text,
583
+ };
584
+ }
585
+ }}
586
+ style={{
587
+ color: 'black',
588
+ fontSize: 24,
589
+ position: 'absolute',
590
+ }}
591
+ />
592
+
593
+ <AnimatedLine animatedProps={doubleArrowsAnimatedPropsLast} />
594
+ </G>
595
+
296
596
  <AnimatedRectangle animatedProps={rectangleAnimatedProps} />
297
597
  <AnimatedPath animatedProps={penAnimatedProps} />
298
598
  </>
@@ -6,6 +6,7 @@ import Animated, {
6
6
  useDerivedValue,
7
7
  } from 'react-native-reanimated';
8
8
  import type { DrawItem } from '../../types';
9
+ import { hslToRgb } from './CurrentAnimatedItem';
9
10
 
10
11
  const styles = StyleSheet.create({
11
12
  textBackground: {
@@ -60,8 +61,10 @@ export default function CurrentAnimatedText({
60
61
 
61
62
  const textAnimatedStyle = useAnimatedStyle(() => {
62
63
  return {
63
- fontSize: 16 + (currentItem.value?.strokeWidth ?? 0),
64
- color: 'white',
64
+ fontSize: 10 + (currentItem.value?.strokeWidth ?? 0) * 2,
65
+ color: currentItem.value?.color
66
+ ? hslToRgb(currentItem.value?.color)
67
+ : 'white',
65
68
  };
66
69
  }, [currentItem.value?.strokeWidth]);
67
70
 
@@ -1,5 +1,6 @@
1
1
  import type { DrawItem, hslColor, DrawState, Action } from '../../types';
2
2
  import { createContext, RefObject } from 'react';
3
+ import { TextInput } from 'react-native';
3
4
  import type { SharedValue } from 'react-native-reanimated';
4
5
  import type ViewShot from 'react-native-view-shot';
5
6
 
@@ -11,6 +12,7 @@ export const DrawContext = createContext<{
11
12
  currentItem?: SharedValue<DrawItem | null>;
12
13
  itemIsSelected?: SharedValue<boolean>;
13
14
  viewShot?: RefObject<ViewShot>;
15
+ doubleArrowTextInput?: RefObject<TextInput>;
14
16
  }>({
15
17
  drawState: {
16
18
  doneItems: [],
@@ -12,24 +12,26 @@ const DrawPad = ({
12
12
  doneItems,
13
13
  onPressItem,
14
14
  onTextHeightChange,
15
+ addBackground = false,
15
16
  }: {
16
17
  currentItem: Animated.SharedValue<DrawItem | null>;
17
18
  doneItems: Array<DrawItem>;
18
19
  onPressItem: (item: DrawItem, index: number) => () => void;
19
20
  onTextHeightChange: (height: number) => void;
21
+ addBackground?: boolean;
20
22
  }) => {
21
23
  return (
22
24
  <>
23
- <Svg>
25
+ <Svg style={addBackground ? { backgroundColor: 'white' } : null}>
24
26
  <Defs>
25
27
  <Circle
26
28
  id="selectionIndicator"
27
29
  fill="#3a6cff"
28
- r={5}
30
+ r={10}
29
31
  cx={0}
30
32
  cy={0}
31
33
  strokeWidth={1}
32
- stroke="white"
34
+ stroke="black"
33
35
  />
34
36
  <Marker
35
37
  id="arrowhead"
@@ -45,6 +47,20 @@ const DrawPad = ({
45
47
  strokeLinejoin="round"
46
48
  />
47
49
  </Marker>
50
+ <Marker
51
+ id="arrowheadStart"
52
+ markerUnits={'strokeWidth' as MarkerUnits}
53
+ refX="0"
54
+ refY="0"
55
+ orient="auto"
56
+ >
57
+ <Polyline
58
+ points="2,-2 0,0 2,2 0,0"
59
+ stroke="context-stroke"
60
+ strokeLinecap="round"
61
+ strokeLinejoin="round"
62
+ />
63
+ </Marker>
48
64
 
49
65
  <Marker
50
66
  id="side"
@@ -76,7 +92,7 @@ const DrawPad = ({
76
92
  <Item key={index} item={item} onPress={onPressItem(item, index)} />
77
93
  ))}
78
94
 
79
- <CurrentAnimatedItem currentItem={currentItem} />
95
+ <CurrentAnimatedItem />
80
96
  </Svg>
81
97
  <CurrentAnimatedText
82
98
  currentItem={currentItem}
@@ -3,6 +3,8 @@ import React, { ReactElement, useMemo, useReducer, useRef } from 'react';
3
3
  import type { Action, DrawItem, DrawState, hslColor } from '../../types';
4
4
  import { useSharedValue } from 'react-native-reanimated';
5
5
  import type ViewShot from 'react-native-view-shot';
6
+ import { Keyboard } from 'react-native';
7
+ import { TextInput } from 'react-native-gesture-handler';
6
8
 
7
9
  const initialState: DrawState = {
8
10
  doneItems: [],
@@ -20,6 +22,7 @@ const reducerDrawStates = (drawState: DrawState, action: Action): DrawState => {
20
22
  cancelEnabled: action.cancelEnabled,
21
23
  };
22
24
  case 'SET_DRAWING_MODE':
25
+ Keyboard.dismiss();
23
26
  return {
24
27
  ...drawState,
25
28
  drawingMode: action.drawingMode,
@@ -87,6 +90,7 @@ const DrawProvider = ({ children }: { children: ReactElement }) => {
87
90
  const color = useSharedValue<hslColor>('hsl(0, 100%, 0%)');
88
91
  const currentItem = useSharedValue<DrawItem | null>(null);
89
92
  const viewShot = useRef<ViewShot>(null);
93
+ const doubleArrowTextInput = useRef<TextInput>(null);
90
94
 
91
95
  const [drawState, dispatchDrawStates] = useReducer(
92
96
  reducerDrawStates,
@@ -102,6 +106,7 @@ const DrawProvider = ({ children }: { children: ReactElement }) => {
102
106
  currentItem,
103
107
  itemIsSelected,
104
108
  viewShot,
109
+ doubleArrowTextInput,
105
110
  }),
106
111
  [
107
112
  drawState,
@@ -111,6 +116,7 @@ const DrawProvider = ({ children }: { children: ReactElement }) => {
111
116
  currentItem,
112
117
  itemIsSelected,
113
118
  viewShot,
119
+ doubleArrowTextInput,
114
120
  ]
115
121
  );
116
122