canvu-react 0.3.34 → 0.3.35

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/react.cjs CHANGED
@@ -1825,6 +1825,67 @@ function useCanvuChromeContext() {
1825
1825
  return react.useContext(CanvuChromeContext);
1826
1826
  }
1827
1827
 
1828
+ // src/math/item-transform.ts
1829
+ init_rect();
1830
+ function getItemRotationRad(item) {
1831
+ return item.rotation ?? 0;
1832
+ }
1833
+ function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
1834
+ const c = { x: w / 2, y: h / 2 };
1835
+ const dlx = lx - c.x;
1836
+ const dly = ly - c.y;
1837
+ const cos = Math.cos(rotationRad);
1838
+ const sin = Math.sin(rotationRad);
1839
+ return {
1840
+ x: itemX + c.x + cos * dlx - sin * dly,
1841
+ y: itemY + c.y + sin * dlx + cos * dly
1842
+ };
1843
+ }
1844
+ function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
1845
+ const c = { x: w / 2, y: h / 2 };
1846
+ const vx = wx - itemX;
1847
+ const vy = wy - itemY;
1848
+ const dx = vx - c.x;
1849
+ const dy = vy - c.y;
1850
+ const cos = Math.cos(-rotationRad);
1851
+ const sin = Math.sin(-rotationRad);
1852
+ const lx = cos * dx - sin * dy;
1853
+ const ly = sin * dx + cos * dy;
1854
+ return { x: c.x + lx, y: c.y + ly };
1855
+ }
1856
+ function itemPivotWorld(item) {
1857
+ const r = normalizeRect(item.bounds);
1858
+ return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
1859
+ }
1860
+ function boundsAabbForRotatedItem(item) {
1861
+ const rot = getItemRotationRad(item);
1862
+ if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
1863
+ return item.bounds;
1864
+ }
1865
+ const r = normalizeRect(item.bounds);
1866
+ if (Math.abs(rot) < 1e-12) {
1867
+ return r;
1868
+ }
1869
+ const corners = [
1870
+ [0, 0],
1871
+ [r.width, 0],
1872
+ [r.width, r.height],
1873
+ [0, r.height]
1874
+ ];
1875
+ let minX = Infinity;
1876
+ let minY = Infinity;
1877
+ let maxX = -Infinity;
1878
+ let maxY = -Infinity;
1879
+ for (const [lx, ly] of corners) {
1880
+ const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
1881
+ minX = Math.min(minX, p.x);
1882
+ minY = Math.min(minY, p.y);
1883
+ maxX = Math.max(maxX, p.x);
1884
+ maxY = Math.max(maxY, p.y);
1885
+ }
1886
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
1887
+ }
1888
+
1828
1889
  // src/scene/clone-item.ts
1829
1890
  init_shape_builders();
1830
1891
  function cloneVectorSceneItemWithNewId(item) {
@@ -1864,20 +1925,25 @@ function markImageAsManaged(item) {
1864
1925
  };
1865
1926
  }
1866
1927
  function restackManagedImages(items) {
1867
- let anchor;
1928
+ let anchorAabbY = Infinity;
1929
+ let anchorCenterX = 0;
1868
1930
  for (const item of items) {
1869
1931
  if (!isManagedImage(item)) continue;
1870
- if (!anchor || item.bounds.y < anchor.bounds.y) anchor = item;
1932
+ const aabb = boundsAabbForRotatedItem(item);
1933
+ if (aabb.y < anchorAabbY) {
1934
+ anchorAabbY = aabb.y;
1935
+ anchorCenterX = aabb.x + aabb.width / 2;
1936
+ }
1871
1937
  }
1872
- if (!anchor) return [...items];
1873
- const anchorCenterX = anchor.bounds.x + anchor.bounds.width / 2;
1874
- const anchorTopY = anchor.bounds.y;
1875
- let cursorY = anchorTopY;
1938
+ if (!Number.isFinite(anchorAabbY)) return [...items];
1939
+ let cursorY = anchorAabbY;
1876
1940
  return items.map((item) => {
1877
1941
  if (!isManagedImage(item)) return item;
1942
+ const aabb = boundsAabbForRotatedItem(item);
1943
+ const centerY = cursorY + aabb.height / 2;
1878
1944
  const newX = anchorCenterX - item.bounds.width / 2;
1879
- const newY = cursorY;
1880
- cursorY = newY + item.bounds.height + STACK_GAP_WORLD;
1945
+ const newY = centerY - item.bounds.height / 2;
1946
+ cursorY += aabb.height + STACK_GAP_WORLD;
1881
1947
  if (item.bounds.x === newX && item.bounds.y === newY) return item;
1882
1948
  return {
1883
1949
  ...item,
@@ -1897,8 +1963,10 @@ function copyManagedImage(items, id) {
1897
1963
  return restackManagedImages(inserted);
1898
1964
  }
1899
1965
  function rotateManagedImage(items, id) {
1900
- return items.map(
1901
- (i) => i.id === id ? { ...i, rotation: ((i.rotation ?? 0) + Math.PI / 2) % (Math.PI * 2) } : i
1966
+ return restackManagedImages(
1967
+ items.map(
1968
+ (i) => i.id === id ? { ...i, rotation: ((i.rotation ?? 0) + Math.PI / 2) % (Math.PI * 2) } : i
1969
+ )
1902
1970
  );
1903
1971
  }
1904
1972
  function deleteManagedImage(items, id) {
@@ -2345,69 +2413,6 @@ function getBoardPositionStyle(position, inset = 12, zIndex = 40) {
2345
2413
  return base2;
2346
2414
  }
2347
2415
  }
2348
-
2349
- // src/math/item-transform.ts
2350
- init_rect();
2351
- function getItemRotationRad(item) {
2352
- return item.rotation ?? 0;
2353
- }
2354
- function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
2355
- const c = { x: w / 2, y: h / 2 };
2356
- const dlx = lx - c.x;
2357
- const dly = ly - c.y;
2358
- const cos = Math.cos(rotationRad);
2359
- const sin = Math.sin(rotationRad);
2360
- return {
2361
- x: itemX + c.x + cos * dlx - sin * dly,
2362
- y: itemY + c.y + sin * dlx + cos * dly
2363
- };
2364
- }
2365
- function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
2366
- const c = { x: w / 2, y: h / 2 };
2367
- const vx = wx - itemX;
2368
- const vy = wy - itemY;
2369
- const dx = vx - c.x;
2370
- const dy = vy - c.y;
2371
- const cos = Math.cos(-rotationRad);
2372
- const sin = Math.sin(-rotationRad);
2373
- const lx = cos * dx - sin * dy;
2374
- const ly = sin * dx + cos * dy;
2375
- return { x: c.x + lx, y: c.y + ly };
2376
- }
2377
- function itemPivotWorld(item) {
2378
- const r = normalizeRect(item.bounds);
2379
- return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
2380
- }
2381
- function boundsAabbForRotatedItem(item) {
2382
- const rot = getItemRotationRad(item);
2383
- if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
2384
- return item.bounds;
2385
- }
2386
- const r = normalizeRect(item.bounds);
2387
- if (Math.abs(rot) < 1e-12) {
2388
- return r;
2389
- }
2390
- const corners = [
2391
- [0, 0],
2392
- [r.width, 0],
2393
- [r.width, r.height],
2394
- [0, r.height]
2395
- ];
2396
- let minX = Infinity;
2397
- let minY = Infinity;
2398
- let maxX = -Infinity;
2399
- let maxY = -Infinity;
2400
- for (const [lx, ly] of corners) {
2401
- const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
2402
- minX = Math.min(minX, p.x);
2403
- minY = Math.min(minY, p.y);
2404
- maxX = Math.max(maxX, p.x);
2405
- maxY = Math.max(maxY, p.y);
2406
- }
2407
- return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
2408
- }
2409
-
2410
- // src/react/navmenu/minimap.tsx
2411
2416
  init_rect();
2412
2417
  var NavMenuMinimapSlotContext = react.createContext(null);
2413
2418
  function noop() {