@jiujue/react-canvas-fiber 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -50,10 +50,92 @@ function createNode(type, props) {
50
50
  node.imageInstance = null;
51
51
  } else if (type === "View") {
52
52
  node.backgroundImageInstance = null;
53
+ } else if (type === "Path") {
54
+ node.path2d = null;
55
+ node.pathSource = null;
53
56
  }
54
57
  return node;
55
58
  }
56
59
 
60
+ // src/utils/style.ts
61
+ function normalizeInsets(style) {
62
+ const paddingHorizontal = style?.paddingHorizontal ?? style?.padding ?? 0;
63
+ const paddingVertical = style?.paddingVertical ?? style?.padding ?? 0;
64
+ const marginHorizontal = style?.marginHorizontal ?? style?.margin ?? 0;
65
+ const marginVertical = style?.marginVertical ?? style?.margin ?? 0;
66
+ return {
67
+ paddingTop: style?.paddingTop ?? paddingVertical,
68
+ paddingRight: style?.paddingRight ?? paddingHorizontal,
69
+ paddingBottom: style?.paddingBottom ?? paddingVertical,
70
+ paddingLeft: style?.paddingLeft ?? paddingHorizontal,
71
+ marginTop: style?.marginTop ?? marginVertical,
72
+ marginRight: style?.marginRight ?? marginHorizontal,
73
+ marginBottom: style?.marginBottom ?? marginVertical,
74
+ marginLeft: style?.marginLeft ?? marginHorizontal
75
+ };
76
+ }
77
+
78
+ // src/utils/path2d.ts
79
+ function resolvePath2D(node) {
80
+ const d = node.props?.d;
81
+ if (typeof d !== "string" || !d.trim()) {
82
+ node.path2d = null;
83
+ node.pathSource = null;
84
+ return null;
85
+ }
86
+ if (node.pathSource === d && node.path2d) return node.path2d;
87
+ try {
88
+ const path = new Path2D(d);
89
+ node.path2d = path;
90
+ node.pathSource = d;
91
+ return path;
92
+ } catch {
93
+ node.path2d = null;
94
+ node.pathSource = d;
95
+ return null;
96
+ }
97
+ }
98
+
99
+ // src/render/drawPrimitives.ts
100
+ function drawPathNode(ctx, node, x, y) {
101
+ const path = resolvePath2D(node);
102
+ if (!path) return;
103
+ const fill = node.props.fill ?? "#ffffff";
104
+ const fillRule = node.props.fillRule;
105
+ const stroke = node.props.stroke;
106
+ const lineWidth = node.props.lineWidth ?? 1;
107
+ ctx.save();
108
+ ctx.translate(x, y);
109
+ if (fill) {
110
+ ctx.fillStyle = fill;
111
+ ctx.fill(path, fillRule);
112
+ }
113
+ if (stroke) {
114
+ ctx.strokeStyle = stroke;
115
+ ctx.lineWidth = lineWidth;
116
+ ctx.stroke(path);
117
+ }
118
+ ctx.restore();
119
+ }
120
+ function drawLineNode(ctx, node, x, y, w, h) {
121
+ const stroke = node.props.stroke ?? "#ffffff";
122
+ const lineWidth = node.props.lineWidth ?? 1;
123
+ const lineCap = node.props.lineCap;
124
+ const x1 = node.props.x1 ?? 0;
125
+ const y1 = node.props.y1 ?? 0;
126
+ const x2 = node.props.x2 ?? w;
127
+ const y2 = node.props.y2 ?? h;
128
+ ctx.save();
129
+ ctx.beginPath();
130
+ ctx.moveTo(x + x1, y + y1);
131
+ ctx.lineTo(x + x2, y + y2);
132
+ ctx.strokeStyle = stroke;
133
+ ctx.lineWidth = lineWidth;
134
+ if (lineCap) ctx.lineCap = lineCap;
135
+ ctx.stroke();
136
+ ctx.restore();
137
+ }
138
+
57
139
  // src/render/drawTree.ts
58
140
  function resolveInheritedTextStyle(node, defaults) {
59
141
  const own = node.props?.style ?? {};
@@ -370,6 +452,36 @@ function drawNode(state, node, offsetX, offsetY) {
370
452
  }
371
453
  ctx.restore();
372
454
  }
455
+ if (node.type === "Circle") {
456
+ const fill = node.props.fill ?? "#ffffff";
457
+ const stroke = node.props.stroke;
458
+ const lineWidth = node.props.lineWidth ?? 1;
459
+ if (w > 0 && h > 0) {
460
+ const cx = x + w / 2;
461
+ const cy = y + h / 2;
462
+ const rx = w / 2;
463
+ const ry = h / 2;
464
+ ctx.save();
465
+ ctx.beginPath();
466
+ ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
467
+ if (fill) {
468
+ ctx.fillStyle = fill;
469
+ ctx.fill();
470
+ }
471
+ if (stroke) {
472
+ ctx.strokeStyle = stroke;
473
+ ctx.lineWidth = lineWidth;
474
+ ctx.stroke();
475
+ }
476
+ ctx.restore();
477
+ }
478
+ }
479
+ if (node.type === "Path") {
480
+ drawPathNode(ctx, node, x, y);
481
+ }
482
+ if (node.type === "Line") {
483
+ drawLineNode(ctx, node, x, y, w, h);
484
+ }
373
485
  if (node.type === "Text") {
374
486
  const text = node.props.text;
375
487
  const color = node.props.color ?? "#ffffff";
@@ -448,26 +560,6 @@ function drawTree(root, ctx, dpr, clearColor, defaults) {
448
560
  }
449
561
  ctx.restore();
450
562
  }
451
-
452
- // src/utils/style.ts
453
- function normalizeInsets(style) {
454
- const paddingHorizontal = style?.paddingHorizontal ?? style?.padding ?? 0;
455
- const paddingVertical = style?.paddingVertical ?? style?.padding ?? 0;
456
- const marginHorizontal = style?.marginHorizontal ?? style?.margin ?? 0;
457
- const marginVertical = style?.marginVertical ?? style?.margin ?? 0;
458
- return {
459
- paddingTop: style?.paddingTop ?? paddingVertical,
460
- paddingRight: style?.paddingRight ?? paddingHorizontal,
461
- paddingBottom: style?.paddingBottom ?? paddingVertical,
462
- paddingLeft: style?.paddingLeft ?? paddingHorizontal,
463
- marginTop: style?.marginTop ?? marginVertical,
464
- marginRight: style?.marginRight ?? marginHorizontal,
465
- marginBottom: style?.marginBottom ?? marginVertical,
466
- marginLeft: style?.marginLeft ?? marginHorizontal
467
- };
468
- }
469
-
470
- // src/layout/layoutTree.ts
471
563
  var layoutEnginePromise = null;
472
564
  function getLayoutEngine() {
473
565
  if (!layoutEnginePromise) {
@@ -934,6 +1026,38 @@ function createReconcilerRoot(container) {
934
1026
  };
935
1027
  }
936
1028
 
1029
+ // src/runtime/hitTestPrimitives.ts
1030
+ function hitTestEllipse(x, y, left, top, width, height) {
1031
+ const rx = width / 2;
1032
+ const ry = height / 2;
1033
+ if (rx <= 0 || ry <= 0) return false;
1034
+ const cx = left + rx;
1035
+ const cy = top + ry;
1036
+ const dx = (x - cx) / rx;
1037
+ const dy = (y - cy) / ry;
1038
+ return dx * dx + dy * dy <= 1;
1039
+ }
1040
+ function hitTestLineSegment(x, y, ax, ay, bx, by, threshold) {
1041
+ const abx = bx - ax;
1042
+ const aby = by - ay;
1043
+ const apx = x - ax;
1044
+ const apy = y - ay;
1045
+ const abLenSq = abx * abx + aby * aby;
1046
+ if (abLenSq <= 1e-9) {
1047
+ const dx2 = x - ax;
1048
+ const dy2 = y - ay;
1049
+ return dx2 * dx2 + dy2 * dy2 <= threshold * threshold;
1050
+ }
1051
+ let t = (apx * abx + apy * aby) / abLenSq;
1052
+ if (t < 0) t = 0;
1053
+ else if (t > 1) t = 1;
1054
+ const px = ax + t * abx;
1055
+ const py = ay + t * aby;
1056
+ const dx = x - px;
1057
+ const dy = y - py;
1058
+ return dx * dx + dy * dy <= threshold * threshold;
1059
+ }
1060
+
937
1061
  // src/runtime/root.ts
938
1062
  function createCanvasRoot(canvas, options) {
939
1063
  const ctx = canvas.getContext("2d");
@@ -1219,6 +1343,37 @@ function createCanvasRoot(canvas, options) {
1219
1343
  const hit = hitTestNode(child, x, y, childOffsetX, childOffsetY);
1220
1344
  if (hit) return hit;
1221
1345
  }
1346
+ if (node.type === "Circle") {
1347
+ const ok = hitTestEllipse(x, y, left, top, node.layout.width, node.layout.height);
1348
+ if (!ok) return null;
1349
+ }
1350
+ if (node.type === "Line") {
1351
+ const w = node.layout.width;
1352
+ const h = node.layout.height;
1353
+ const x1 = node.props.x1 ?? 0;
1354
+ const y1 = node.props.y1 ?? 0;
1355
+ const x2 = node.props.x2 ?? w;
1356
+ const y2 = node.props.y2 ?? h;
1357
+ const lineWidth = node.props.lineWidth ?? 1;
1358
+ const threshold = Math.max(1, lineWidth / 2);
1359
+ const ok = hitTestLineSegment(x, y, left + x1, top + y1, left + x2, top + y2, threshold);
1360
+ if (!ok) return null;
1361
+ }
1362
+ if (node.type === "Path") {
1363
+ const path = resolvePath2D(node);
1364
+ if (!path) return null;
1365
+ const fillRule = node.props.fillRule;
1366
+ const stroke = node.props.stroke;
1367
+ const lineWidth = node.props.lineWidth ?? 1;
1368
+ ctx.save();
1369
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
1370
+ ctx.translate(left, top);
1371
+ ctx.lineWidth = lineWidth;
1372
+ const inFill = ctx.isPointInPath(path, x, y, fillRule);
1373
+ const inStroke = stroke ? ctx.isPointInStroke(path, x, y) : false;
1374
+ ctx.restore();
1375
+ if (!inFill && !inStroke) return null;
1376
+ }
1222
1377
  return node;
1223
1378
  };
1224
1379
  const hitTestScrollbarThumbNode = (node, x, y, offsetX, offsetY) => {
@@ -1897,6 +2052,15 @@ function View(props) {
1897
2052
  function Rect(props) {
1898
2053
  return react.createElement("Rect", props);
1899
2054
  }
2055
+ function Circle(props) {
2056
+ return react.createElement("Circle", props);
2057
+ }
2058
+ function Path(props) {
2059
+ return react.createElement("Path", props);
2060
+ }
2061
+ function Line(props) {
2062
+ return react.createElement("Line", props);
2063
+ }
1900
2064
  function Text(props) {
1901
2065
  return react.createElement("Text", props);
1902
2066
  }
@@ -1905,7 +2069,10 @@ function Image2(props) {
1905
2069
  }
1906
2070
 
1907
2071
  exports.Canvas = Canvas;
2072
+ exports.Circle = Circle;
1908
2073
  exports.Image = Image2;
2074
+ exports.Line = Line;
2075
+ exports.Path = Path;
1909
2076
  exports.Rect = Rect;
1910
2077
  exports.Text = Text;
1911
2078
  exports.View = View;