canvu-react 0.4.57 → 0.4.59

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/native.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import getStroke from 'perfect-freehand';
2
2
  import { Group, Canvas, Rect, Circle, Path, RoundedRect, Oval, DashPathEffect, Line, vec, matchFont, Text as Text$1, Image } from '@shopify/react-native-skia';
3
- import { memo, forwardRef, useState, useRef, useEffect, useCallback, useMemo, useImperativeHandle } from 'react';
3
+ import { memo, useRef, useMemo, forwardRef, useState, useImperativeHandle, useEffect, useCallback } from 'react';
4
4
  import { StyleSheet, PanResponder, View, Modal, Text, TextInput, Pressable, ScrollView, Image as Image$1 } from 'react-native';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
 
@@ -3835,6 +3835,47 @@ function cullItemsByViewport(items, visibleWorld) {
3835
3835
  }
3836
3836
  return cullItemsByViewportSpatial(items, visibleWorld, SPATIAL_CELL_SIZE);
3837
3837
  }
3838
+
3839
+ // src/native/native-scene-culling.ts
3840
+ var NATIVE_SCENE_CULL_OVERSCAN_RATIO = 0.5;
3841
+ function expandRect(rect, ratio) {
3842
+ const safeRatio = Number.isFinite(ratio) ? Math.max(0, ratio) : 0;
3843
+ const insetX = rect.width * safeRatio;
3844
+ const insetY = rect.height * safeRatio;
3845
+ return {
3846
+ x: rect.x - insetX,
3847
+ y: rect.y - insetY,
3848
+ width: rect.width + insetX * 2,
3849
+ height: rect.height + insetY * 2
3850
+ };
3851
+ }
3852
+ function rectContainsRect(outer, inner) {
3853
+ return inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.width <= outer.x + outer.width && inner.y + inner.height <= outer.y + outer.height;
3854
+ }
3855
+ function resolveNativeSceneVisibleItems({
3856
+ items,
3857
+ visibleWorld,
3858
+ cache,
3859
+ overscanRatio = NATIVE_SCENE_CULL_OVERSCAN_RATIO
3860
+ }) {
3861
+ if (cache && cache.items === items && rectContainsRect(cache.cullRect, visibleWorld)) {
3862
+ return {
3863
+ cache,
3864
+ visible: cache.visible
3865
+ };
3866
+ }
3867
+ const cullRect = expandRect(visibleWorld, overscanRatio);
3868
+ const visible = cullItemsByViewport(items, cullRect);
3869
+ const nextCache = {
3870
+ items,
3871
+ cullRect,
3872
+ visible
3873
+ };
3874
+ return {
3875
+ cache: nextCache,
3876
+ visible
3877
+ };
3878
+ }
3838
3879
  var MemoShape = memo(function MemoShape2({
3839
3880
  item
3840
3881
  }) {
@@ -3855,13 +3896,20 @@ var NativeSceneRenderer = memo(function NativeSceneRenderer2({
3855
3896
  height,
3856
3897
  renderTick
3857
3898
  }) {
3899
+ const visibleCacheRef = useRef(null);
3858
3900
  const cameraTransform = skiaCameraTransform(camera.zoom, camera.x, camera.y);
3859
- const visible = cullItemsByViewport(
3901
+ const resolvedVisible = resolveNativeSceneVisibleItems({
3860
3902
  items,
3861
- camera.getVisibleWorldRect(width, height)
3903
+ visibleWorld: width > 0 && height > 0 ? camera.getVisibleWorldRect(width, height) : { x: 0, y: 0, width: 0, height: 0 },
3904
+ cache: visibleCacheRef.current
3905
+ });
3906
+ visibleCacheRef.current = resolvedVisible.cache;
3907
+ const shapeElements = useMemo(
3908
+ () => resolvedVisible.visible.map((item) => /* @__PURE__ */ jsx(MemoShape, { item }, item.id)),
3909
+ [resolvedVisible.visible]
3862
3910
  );
3863
3911
  if (width <= 0 || height <= 0) return null;
3864
- return /* @__PURE__ */ jsx(Canvas, { style: { width, height }, children: /* @__PURE__ */ jsx(Group, { transform: cameraTransform, children: visible.map((item) => /* @__PURE__ */ jsx(MemoShape, { item }, item.id)) }) });
3912
+ return /* @__PURE__ */ jsx(Canvas, { style: { width, height }, children: /* @__PURE__ */ jsx(Group, { transform: cameraTransform, children: shapeElements }) });
3865
3913
  });
3866
3914
 
3867
3915
  // src/native/native-style-inspector-values.ts
@@ -5541,6 +5589,58 @@ function NativeSelectionContextMenuButton({
5541
5589
  }
5542
5590
  );
5543
5591
  }
5592
+ var NativeCameraRenderLayer = forwardRef(function NativeCameraRenderLayer2({
5593
+ items,
5594
+ camera,
5595
+ width,
5596
+ height,
5597
+ interactive,
5598
+ selectedItems,
5599
+ showResizeHandles,
5600
+ placementPreview,
5601
+ laserTrail,
5602
+ eraserTrail,
5603
+ eraserPreviewItems,
5604
+ previewStrokeStyle,
5605
+ remotePresence
5606
+ }, ref) {
5607
+ const [cameraTick, setCameraTick] = useState(0);
5608
+ useImperativeHandle(
5609
+ ref,
5610
+ () => ({
5611
+ requestRender: () => setCameraTick((n) => n + 1)
5612
+ }),
5613
+ []
5614
+ );
5615
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
5616
+ /* @__PURE__ */ jsx(
5617
+ NativeSceneRenderer,
5618
+ {
5619
+ items,
5620
+ camera,
5621
+ width,
5622
+ height,
5623
+ renderTick: cameraTick
5624
+ }
5625
+ ),
5626
+ interactive && /* @__PURE__ */ jsx(
5627
+ NativeInteractionOverlay,
5628
+ {
5629
+ camera,
5630
+ width,
5631
+ height,
5632
+ selectedItems,
5633
+ showResizeHandles,
5634
+ placementPreview,
5635
+ laserTrail,
5636
+ eraserTrail,
5637
+ eraserPreviewItems,
5638
+ previewStrokeStyle,
5639
+ remotePresence
5640
+ }
5641
+ )
5642
+ ] });
5643
+ });
5544
5644
  var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
5545
5645
  items,
5546
5646
  selectedIds = [],
@@ -5568,6 +5668,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
5568
5668
  }, ref) {
5569
5669
  const [size, setSize] = useState({ width: 0, height: 0 });
5570
5670
  const cameraRef = useRef(null);
5671
+ const cameraRenderLayerRef = useRef(null);
5571
5672
  const toolIdRef = useRef(toolId);
5572
5673
  toolIdRef.current = toolId;
5573
5674
  const toolLockedRef = useRef(toolLocked);
@@ -5762,7 +5863,6 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
5762
5863
  cameraRef.current = new Camera2D({ minZoom: 0.05, maxZoom: 32 });
5763
5864
  }
5764
5865
  const camera = cameraRef.current;
5765
- const [cameraTick, setCameraTick] = useState(0);
5766
5866
  const selectedItems = useMemo(
5767
5867
  () => activeItems.filter((item) => selectedIds.includes(item.id)),
5768
5868
  [activeItems, selectedIds]
@@ -5839,7 +5939,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
5839
5939
  onWorldPointerLeaveRef.current?.();
5840
5940
  }, []);
5841
5941
  const requestRender = useCallback(() => {
5842
- setCameraTick((n) => n + 1);
5942
+ cameraRenderLayerRef.current?.requestRender();
5843
5943
  onCameraChangeRef.current?.();
5844
5944
  }, []);
5845
5945
  const onLayout = useCallback((e) => {
@@ -6746,7 +6846,7 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
6746
6846
  const nativeLinkCanSubmit = pendingNativeLinkRequest !== null && normalizedNativeLinkHref !== null && onItemsChange != null;
6747
6847
  return /* @__PURE__ */ jsxs(View, { style: { flex: 1, overflow: "hidden" }, onLayout, children: [
6748
6848
  size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
6749
- /* @__PURE__ */ jsxs(
6849
+ /* @__PURE__ */ jsx(
6750
6850
  View,
6751
6851
  {
6752
6852
  style: StyleSheet.absoluteFill,
@@ -6759,34 +6859,25 @@ var NativeVectorViewport = forwardRef(function NativeVectorViewport2({
6759
6859
  notifyWorldPointerLeave();
6760
6860
  },
6761
6861
  ...panResponder.panHandlers,
6762
- children: [
6763
- /* @__PURE__ */ jsx(
6764
- NativeSceneRenderer,
6765
- {
6766
- items: sceneItems,
6767
- camera,
6768
- width: size.width,
6769
- height: size.height,
6770
- renderTick: cameraTick
6771
- }
6772
- ),
6773
- interactive && /* @__PURE__ */ jsx(
6774
- NativeInteractionOverlay,
6775
- {
6776
- camera,
6777
- width: size.width,
6778
- height: size.height,
6779
- selectedItems,
6780
- showResizeHandles,
6781
- placementPreview,
6782
- laserTrail,
6783
- eraserTrail,
6784
- eraserPreviewItems,
6785
- previewStrokeStyle: strokeStyleState,
6786
- remotePresence
6787
- }
6788
- )
6789
- ]
6862
+ children: /* @__PURE__ */ jsx(
6863
+ NativeCameraRenderLayer,
6864
+ {
6865
+ ref: cameraRenderLayerRef,
6866
+ items: sceneItems,
6867
+ camera,
6868
+ width: size.width,
6869
+ height: size.height,
6870
+ interactive,
6871
+ selectedItems,
6872
+ showResizeHandles,
6873
+ placementPreview,
6874
+ laserTrail,
6875
+ eraserTrail,
6876
+ eraserPreviewItems,
6877
+ previewStrokeStyle: strokeStyleState,
6878
+ remotePresence
6879
+ }
6880
+ )
6790
6881
  }
6791
6882
  ),
6792
6883
  overlay ? /* @__PURE__ */ jsx(