@vizij/render 0.0.7 → 0.1.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.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { ComponentProps, ReactNode, RefObject } from 'react';
3
+ import { CSSProperties, ComponentProps, ReactNode, RefObject, MouseEvent } from 'react';
4
4
  import { Canvas, ThreeEvent } from '@react-three/fiber';
5
5
  import * as zustand from 'zustand';
6
6
  import * as THREE from 'three';
@@ -8,11 +8,12 @@ import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry, AnimationClip, O
8
8
  import { RawValue, AnimatableValue, RawVector2 } from '@vizij/utils';
9
9
 
10
10
  interface VizijProps {
11
- style?: React.CSSProperties;
11
+ style?: CSSProperties;
12
12
  className?: string;
13
13
  rootId: string;
14
14
  namespace?: string;
15
15
  showSafeArea?: boolean;
16
+ showSelectionGlow?: boolean;
16
17
  onPointerMissed?: ComponentProps<typeof Canvas>["onPointerMissed"];
17
18
  }
18
19
  /**
@@ -30,7 +31,7 @@ interface VizijProps {
30
31
  *
31
32
  * @returns The rendered ReactNode.
32
33
  */
33
- declare function Vizij({ style, className, rootId, namespace, showSafeArea, onPointerMissed, }: VizijProps): ReactNode;
34
+ declare function Vizij({ style, className, rootId, namespace, showSafeArea, showSelectionGlow, onPointerMissed, }: VizijProps): ReactNode;
34
35
  interface InnerVizijProps {
35
36
  rootId: string;
36
37
  namespace: string;
@@ -40,8 +41,9 @@ interface InnerVizijProps {
40
41
  resolution: number;
41
42
  };
42
43
  showSafeArea?: boolean;
44
+ showSelectionGlow?: boolean;
43
45
  }
44
- declare function InnerVizij({ rootId, namespace, container, showSafeArea, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
46
+ declare function InnerVizij({ rootId, namespace, container, showSafeArea, showSelectionGlow, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
45
47
 
46
48
  /**
47
49
  * A wrapping type to reference an attribute that is animatable.
@@ -298,6 +300,7 @@ interface VizijPoseDefinition {
298
300
  id: VizijPoseId;
299
301
  name?: string;
300
302
  description?: string;
303
+ group?: string | null;
301
304
  values: Record<string, number | undefined>;
302
305
  }
303
306
  interface VizijPoseRigConfig {
@@ -420,6 +423,11 @@ interface VizijData {
420
423
  }
421
424
  interface VizijActions {
422
425
  setValue: (id: string, namespace: string, value: RawValue | ((current: RawValue | undefined) => RawValue | undefined)) => void;
426
+ setValues: (writes: Array<{
427
+ id: string;
428
+ namespace: string;
429
+ value: RawValue;
430
+ }>) => void;
423
431
  setWorldElementName: (id: string, value: string) => void;
424
432
  setVizij: (scene: World, animatables: Record<string, AnimatableValue>) => void;
425
433
  setSlot: (parentId: string, parentNamespace: string, childId: string, childNamespace: string) => void;
@@ -471,6 +479,11 @@ declare const VizijSlice: (set: VizijStoreSetter, get: VizijStoreGetter) => {
471
479
  getExportableBodies: (filterIds?: string[]) => THREE.Group<THREE.Object3DEventMap>[];
472
480
  setGeometry: (id: string, geometry: THREE.BufferGeometry) => void;
473
481
  setValue: (id: string, namespace: string, value: RawValue | ((current: RawValue | undefined) => RawValue | undefined)) => void;
482
+ setValues: (writes?: Array<{
483
+ id: string;
484
+ namespace: string;
485
+ value: RawValue;
486
+ }>) => void;
474
487
  setWorldElementName: (id: string, value: string) => void;
475
488
  setParent: (id: string, parent: string) => void;
476
489
  setChild: (id: string, child: string) => void;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { ComponentProps, ReactNode, RefObject } from 'react';
3
+ import { CSSProperties, ComponentProps, ReactNode, RefObject, MouseEvent } from 'react';
4
4
  import { Canvas, ThreeEvent } from '@react-three/fiber';
5
5
  import * as zustand from 'zustand';
6
6
  import * as THREE from 'three';
@@ -8,11 +8,12 @@ import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry, AnimationClip, O
8
8
  import { RawValue, AnimatableValue, RawVector2 } from '@vizij/utils';
9
9
 
10
10
  interface VizijProps {
11
- style?: React.CSSProperties;
11
+ style?: CSSProperties;
12
12
  className?: string;
13
13
  rootId: string;
14
14
  namespace?: string;
15
15
  showSafeArea?: boolean;
16
+ showSelectionGlow?: boolean;
16
17
  onPointerMissed?: ComponentProps<typeof Canvas>["onPointerMissed"];
17
18
  }
18
19
  /**
@@ -30,7 +31,7 @@ interface VizijProps {
30
31
  *
31
32
  * @returns The rendered ReactNode.
32
33
  */
33
- declare function Vizij({ style, className, rootId, namespace, showSafeArea, onPointerMissed, }: VizijProps): ReactNode;
34
+ declare function Vizij({ style, className, rootId, namespace, showSafeArea, showSelectionGlow, onPointerMissed, }: VizijProps): ReactNode;
34
35
  interface InnerVizijProps {
35
36
  rootId: string;
36
37
  namespace: string;
@@ -40,8 +41,9 @@ interface InnerVizijProps {
40
41
  resolution: number;
41
42
  };
42
43
  showSafeArea?: boolean;
44
+ showSelectionGlow?: boolean;
43
45
  }
44
- declare function InnerVizij({ rootId, namespace, container, showSafeArea, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
46
+ declare function InnerVizij({ rootId, namespace, container, showSafeArea, showSelectionGlow, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
45
47
 
46
48
  /**
47
49
  * A wrapping type to reference an attribute that is animatable.
@@ -298,6 +300,7 @@ interface VizijPoseDefinition {
298
300
  id: VizijPoseId;
299
301
  name?: string;
300
302
  description?: string;
303
+ group?: string | null;
301
304
  values: Record<string, number | undefined>;
302
305
  }
303
306
  interface VizijPoseRigConfig {
@@ -420,6 +423,11 @@ interface VizijData {
420
423
  }
421
424
  interface VizijActions {
422
425
  setValue: (id: string, namespace: string, value: RawValue | ((current: RawValue | undefined) => RawValue | undefined)) => void;
426
+ setValues: (writes: Array<{
427
+ id: string;
428
+ namespace: string;
429
+ value: RawValue;
430
+ }>) => void;
423
431
  setWorldElementName: (id: string, value: string) => void;
424
432
  setVizij: (scene: World, animatables: Record<string, AnimatableValue>) => void;
425
433
  setSlot: (parentId: string, parentNamespace: string, childId: string, childNamespace: string) => void;
@@ -471,6 +479,11 @@ declare const VizijSlice: (set: VizijStoreSetter, get: VizijStoreGetter) => {
471
479
  getExportableBodies: (filterIds?: string[]) => THREE.Group<THREE.Object3DEventMap>[];
472
480
  setGeometry: (id: string, geometry: THREE.BufferGeometry) => void;
473
481
  setValue: (id: string, namespace: string, value: RawValue | ((current: RawValue | undefined) => RawValue | undefined)) => void;
482
+ setValues: (writes?: Array<{
483
+ id: string;
484
+ namespace: string;
485
+ value: RawValue;
486
+ }>) => void;
474
487
  setWorldElementName: (id: string, value: string) => void;
475
488
  setParent: (id: string, parent: string) => void;
476
489
  setChild: (id: string, child: string) => void;
package/dist/index.js CHANGED
@@ -55,12 +55,12 @@ __export(index_exports, {
55
55
  module.exports = __toCommonJS(index_exports);
56
56
 
57
57
  // src/vizij.tsx
58
- var import_react10 = require("react");
58
+ var import_react11 = require("react");
59
59
  var import_react_error_boundary = require("react-error-boundary");
60
- var import_three = require("three");
61
- var import_fiber = require("@react-three/fiber");
60
+ var import_three2 = require("three");
61
+ var import_fiber2 = require("@react-three/fiber");
62
62
  var import_drei3 = require("@react-three/drei");
63
- var import_shallow7 = require("zustand/react/shallow");
63
+ var import_shallow8 = require("zustand/react/shallow");
64
64
 
65
65
  // src/renderables/renderable.tsx
66
66
  var import_react8 = require("react");
@@ -174,7 +174,7 @@ function InnerRenderedGroup({
174
174
  namespace,
175
175
  chain
176
176
  }) {
177
- const ref = (0, import_react4.useRef)();
177
+ const ref = (0, import_react4.useRef)(null);
178
178
  const group = useVizijStore((0, import_shallow2.useShallow)((state) => state.world[id]));
179
179
  const refIsNull = !group.refs[namespace]?.current;
180
180
  const animatables = useVizijStore((0, import_shallow2.useShallow)((state) => state.animatables));
@@ -295,9 +295,11 @@ function InnerRenderedEllipse({
295
295
  namespace,
296
296
  chain
297
297
  }) {
298
- const ellipseRef = (0, import_react5.useRef)();
299
- const materialRef = (0, import_react5.useRef)();
300
- const lineRef = (0, import_react5.useRef)();
298
+ const ellipseRef = (0, import_react5.useRef)(null);
299
+ const materialRef = (0, import_react5.useRef)(
300
+ null
301
+ );
302
+ const lineRef = (0, import_react5.useRef)(null);
301
303
  const strokeOffsetRef = (0, import_react5.useRef)(0);
302
304
  const strokeWidthRef = (0, import_react5.useRef)(0);
303
305
  const onElementClick = useVizijStore(
@@ -580,9 +582,11 @@ function InnerRenderedRectangle({
580
582
  namespace,
581
583
  chain
582
584
  }) {
583
- const rectangleRef = (0, import_react6.useRef)();
584
- const materialRef = (0, import_react6.useRef)();
585
- const lineRef = (0, import_react6.useRef)();
585
+ const rectangleRef = (0, import_react6.useRef)(null);
586
+ const materialRef = (0, import_react6.useRef)(
587
+ null
588
+ );
589
+ const lineRef = (0, import_react6.useRef)(null);
586
590
  const strokeOffsetRef = (0, import_react6.useRef)(0);
587
591
  const strokeWidthRef = (0, import_react6.useRef)(0);
588
592
  const onElementClick = useVizijStore(
@@ -867,8 +871,8 @@ function InnerRenderedShape({
867
871
  namespace,
868
872
  chain
869
873
  }) {
870
- const refGroup = (0, import_react7.useRef)();
871
- const ref = (0, import_react7.useRef)();
874
+ const refGroup = (0, import_react7.useRef)(null);
875
+ const ref = (0, import_react7.useRef)(null);
872
876
  const shape = useVizijStore((0, import_shallow5.useShallow)((state) => state.world[id]));
873
877
  const refs = useVizijStore(
874
878
  (0, import_shallow5.useShallow)((state) => state.world[id].refs)
@@ -909,7 +913,7 @@ function InnerRenderedShape({
909
913
  }),
910
914
  [shape, animatableValues, selectionData]
911
915
  );
912
- const material = (0, import_react7.useRef)();
916
+ const material = (0, import_react7.useRef)(null);
913
917
  const morphTargetSettings = (0, import_react7.useMemo)(() => {
914
918
  if (shape.morphTargets) {
915
919
  const dictionary = shape.morphTargets.reduce(
@@ -1555,6 +1559,19 @@ var VizijSlice = (set, get) => ({
1555
1559
  })
1556
1560
  );
1557
1561
  },
1562
+ setValues: (writes = []) => {
1563
+ if (writes.length === 0) {
1564
+ return;
1565
+ }
1566
+ set(
1567
+ (0, import_immer.produce)((state) => {
1568
+ writes.forEach(({ id, namespace, value }) => {
1569
+ const lookupId = (0, import_utils6.getLookup)(namespace, id);
1570
+ state.values.set(lookupId, value);
1571
+ });
1572
+ })
1573
+ );
1574
+ },
1558
1575
  setWorldElementName: (id, value) => {
1559
1576
  set(
1560
1577
  (0, import_immer.produce)((state) => {
@@ -1749,59 +1766,163 @@ var createVizijStore = (initial) => (0, import_zustand2.create)()(
1749
1766
  }))
1750
1767
  );
1751
1768
 
1752
- // src/vizij.tsx
1769
+ // src/effects/selection-glow-effect.tsx
1770
+ var import_react10 = require("react");
1771
+ var import_fiber = require("@react-three/fiber");
1772
+ var import_shallow7 = require("zustand/react/shallow");
1773
+ var import_three = require("three");
1753
1774
  var import_jsx_runtime6 = require("react/jsx-runtime");
1754
- import_three.Object3D.DEFAULT_UP.set(0, 0, 1);
1775
+ function SelectionGlowEffect({
1776
+ enabled = false,
1777
+ color = "#ff1010ff",
1778
+ opacity = 0.9,
1779
+ thresholdAngle = 2
1780
+ }) {
1781
+ const selections = useVizijStore(
1782
+ (0, import_shallow7.useShallow)(
1783
+ (state) => enabled ? state.elementSelection ?? [] : []
1784
+ )
1785
+ );
1786
+ if (!enabled || selections.length === 0) {
1787
+ return null;
1788
+ }
1789
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react10.Fragment, { children: selections.map((selection) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1790
+ SelectionOutline,
1791
+ {
1792
+ selection,
1793
+ color: selection.color ?? color,
1794
+ opacity,
1795
+ thresholdAngle
1796
+ },
1797
+ `${selection.namespace}:${selection.id}`
1798
+ )) });
1799
+ }
1800
+ function SelectionOutline({
1801
+ selection,
1802
+ color,
1803
+ opacity,
1804
+ thresholdAngle
1805
+ }) {
1806
+ const target = useVizijStore(
1807
+ (0, import_shallow7.useShallow)((state) => {
1808
+ const entry = state.world[selection.id];
1809
+ const ref = entry?.refs?.[selection.namespace];
1810
+ const geometry = entry?.geometry ?? null;
1811
+ return { ref, geometry };
1812
+ })
1813
+ );
1814
+ const sourceRef = target.ref;
1815
+ const edgesGeometry = (0, import_react10.useMemo)(() => {
1816
+ if (!target.geometry) return null;
1817
+ const edges = new import_three.EdgesGeometry(target.geometry, thresholdAngle);
1818
+ return edges;
1819
+ }, [target.geometry, thresholdAngle]);
1820
+ (0, import_react10.useEffect)(() => () => edgesGeometry?.dispose(), [edgesGeometry]);
1821
+ const material = (0, import_react10.useMemo)(() => {
1822
+ const mat = new import_three.LineBasicMaterial({
1823
+ color: new import_three.Color(color),
1824
+ transparent: true,
1825
+ opacity,
1826
+ blending: import_three.AdditiveBlending,
1827
+ depthTest: false,
1828
+ depthWrite: false,
1829
+ toneMapped: false
1830
+ });
1831
+ return mat;
1832
+ }, [color, opacity]);
1833
+ (0, import_react10.useEffect)(() => () => material.dispose(), [material]);
1834
+ const lineRef = (0, import_react10.useRef)(null);
1835
+ (0, import_fiber.useFrame)(() => {
1836
+ const source = sourceRef?.current;
1837
+ const line = lineRef.current;
1838
+ if (!source || !line) return;
1839
+ copyWorldTransform(source, line);
1840
+ line.visible = source.visible;
1841
+ });
1842
+ if (!sourceRef || !edgesGeometry) {
1843
+ return null;
1844
+ }
1845
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1846
+ "lineSegments",
1847
+ {
1848
+ ref: lineRef,
1849
+ geometry: edgesGeometry,
1850
+ material,
1851
+ frustumCulled: false,
1852
+ renderOrder: 1e3
1853
+ }
1854
+ );
1855
+ }
1856
+ var tempMatrix = new import_three.Matrix4();
1857
+ var tempPosition = new import_three.Vector3();
1858
+ var tempQuaternion = new import_three.Quaternion();
1859
+ var tempScale = new import_three.Vector3();
1860
+ function copyWorldTransform(source, target) {
1861
+ source.updateWorldMatrix(true, false);
1862
+ tempMatrix.copy(source.matrixWorld);
1863
+ tempMatrix.decompose(tempPosition, tempQuaternion, tempScale);
1864
+ target.position.copy(tempPosition);
1865
+ target.quaternion.copy(tempQuaternion);
1866
+ target.scale.copy(tempScale);
1867
+ target.updateMatrix();
1868
+ }
1869
+
1870
+ // src/vizij.tsx
1871
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1872
+ import_three2.Object3D.DEFAULT_UP.set(0, 0, 1);
1755
1873
  function Vizij({
1756
1874
  style,
1757
1875
  className,
1758
1876
  rootId,
1759
1877
  namespace = "default",
1760
1878
  showSafeArea = false,
1879
+ showSelectionGlow = false,
1761
1880
  onPointerMissed
1762
1881
  }) {
1763
- const ctx = (0, import_react10.useContext)(VizijContext);
1882
+ const ctx = (0, import_react11.useContext)(VizijContext);
1764
1883
  if (ctx) {
1765
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1766
- import_fiber.Canvas,
1884
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1885
+ import_fiber2.Canvas,
1767
1886
  {
1768
1887
  shadows: false,
1769
1888
  style,
1770
1889
  className,
1771
1890
  onPointerMissed,
1772
1891
  gl: {
1773
- outputColorSpace: import_three.SRGBColorSpace,
1774
- toneMapping: import_three.NoToneMapping,
1892
+ outputColorSpace: import_three2.SRGBColorSpace,
1893
+ toneMapping: import_three2.NoToneMapping,
1775
1894
  antialias: true
1776
1895
  },
1777
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1896
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1778
1897
  MemoizedInnerVizij,
1779
1898
  {
1780
1899
  rootId,
1781
1900
  namespace,
1782
- showSafeArea
1901
+ showSafeArea,
1902
+ showSelectionGlow
1783
1903
  }
1784
1904
  )
1785
1905
  }
1786
1906
  );
1787
1907
  } else {
1788
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VizijContext.Provider, { value: useDefaultVizijStore, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1789
- import_fiber.Canvas,
1908
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VizijContext.Provider, { value: useDefaultVizijStore, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1909
+ import_fiber2.Canvas,
1790
1910
  {
1791
1911
  style,
1792
1912
  className,
1793
1913
  onPointerMissed,
1794
1914
  gl: {
1795
- outputColorSpace: import_three.SRGBColorSpace,
1796
- toneMapping: import_three.NoToneMapping,
1915
+ outputColorSpace: import_three2.SRGBColorSpace,
1916
+ toneMapping: import_three2.NoToneMapping,
1797
1917
  antialias: true
1798
1918
  },
1799
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1919
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1800
1920
  MemoizedInnerVizij,
1801
1921
  {
1802
1922
  rootId,
1803
1923
  namespace,
1804
- showSafeArea
1924
+ showSafeArea,
1925
+ showSelectionGlow
1805
1926
  }
1806
1927
  )
1807
1928
  }
@@ -1812,15 +1933,16 @@ function InnerVizij({
1812
1933
  rootId,
1813
1934
  namespace = "default",
1814
1935
  container,
1815
- showSafeArea
1936
+ showSafeArea,
1937
+ showSelectionGlow
1816
1938
  }) {
1817
1939
  const sceneParentSizing = container ? {
1818
1940
  width: container.width * container.resolution,
1819
1941
  height: container.height * container.resolution
1820
1942
  } : void 0;
1821
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1822
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ambientLight", { intensity: Math.PI / 2 }),
1823
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1943
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1944
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ambientLight", { intensity: Math.PI / 2 }),
1945
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1824
1946
  import_drei3.OrthographicCamera,
1825
1947
  {
1826
1948
  makeDefault: true,
@@ -1829,7 +1951,7 @@ function InnerVizij({
1829
1951
  far: 101
1830
1952
  }
1831
1953
  ),
1832
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react10.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1954
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react11.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1833
1955
  World,
1834
1956
  {
1835
1957
  rootId,
@@ -1837,27 +1959,28 @@ function InnerVizij({
1837
1959
  parentSizing: sceneParentSizing
1838
1960
  }
1839
1961
  ) }),
1840
- showSafeArea && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SafeAreaRenderer, { rootId })
1962
+ showSelectionGlow && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SelectionGlowEffect, { enabled: true }),
1963
+ showSafeArea && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SafeAreaRenderer, { rootId })
1841
1964
  ] });
1842
1965
  }
1843
- var MemoizedInnerVizij = (0, import_react10.memo)(InnerVizij);
1966
+ var MemoizedInnerVizij = (0, import_react11.memo)(InnerVizij);
1844
1967
  function InnerWorld({
1845
1968
  rootId,
1846
1969
  namespace = "default",
1847
1970
  parentSizing
1848
1971
  }) {
1849
1972
  const [present, rootBounds] = useVizijStore(
1850
- (0, import_shallow7.useShallow)((state) => {
1973
+ (0, import_shallow8.useShallow)((state) => {
1851
1974
  const group = state.world[rootId];
1852
1975
  const bounds = group?.rootBounds ?? defaultRootBounds;
1853
1976
  return [group !== void 0, bounds];
1854
1977
  })
1855
1978
  );
1856
- const { camera, size } = (0, import_fiber.useThree)((state) => ({
1979
+ const { camera, size } = (0, import_fiber2.useThree)((state) => ({
1857
1980
  camera: state.camera,
1858
1981
  size: state.size
1859
1982
  }));
1860
- (0, import_react10.useEffect)(() => {
1983
+ (0, import_react11.useEffect)(() => {
1861
1984
  const width = rootBounds.size.x;
1862
1985
  const height = rootBounds.size.y;
1863
1986
  if (camera && parentSizing === void 0 && camera.isOrthographicCamera) {
@@ -1885,9 +2008,9 @@ function InnerWorld({
1885
2008
  camera.updateProjectionMatrix();
1886
2009
  }
1887
2010
  }, [rootBounds, camera, parentSizing, size]);
1888
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_error_boundary.ErrorBoundary, { fallback: null, children: [
1889
- present && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Renderable, { id: rootId, namespace, chain: [] }),
1890
- !present && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2011
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_error_boundary.ErrorBoundary, { fallback: null, children: [
2012
+ present && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Renderable, { id: rootId, namespace, chain: [] }),
2013
+ !present && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1891
2014
  import_drei3.Text,
1892
2015
  {
1893
2016
  position: [0, 0, 0],
@@ -1900,7 +2023,7 @@ function InnerWorld({
1900
2023
  )
1901
2024
  ] });
1902
2025
  }
1903
- var World = (0, import_react10.memo)(InnerWorld);
2026
+ var World = (0, import_react11.memo)(InnerWorld);
1904
2027
  function SafeAreaRenderer({ rootId }) {
1905
2028
  const rootBounds = useVizijStore((state) => {
1906
2029
  const group = state.world[rootId];
@@ -1910,7 +2033,7 @@ function SafeAreaRenderer({ rootId }) {
1910
2033
  const right = rootBounds.center.x + rootBounds.size.x / 2;
1911
2034
  const top = rootBounds.center.y + rootBounds.size.y / 2;
1912
2035
  const bottom = rootBounds.center.y - rootBounds.size.y / 2;
1913
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2036
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1914
2037
  import_drei3.Line,
1915
2038
  {
1916
2039
  points: [
@@ -1941,11 +2064,11 @@ var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
1941
2064
  })(ShapeMaterial || {});
1942
2065
 
1943
2066
  // src/hooks/use-vizij-store-subscription.ts
1944
- var import_react11 = require("react");
2067
+ var import_react12 = require("react");
1945
2068
  function useVizijStoreSubscription(selector, listener) {
1946
- const store = (0, import_react11.useContext)(VizijContext);
2069
+ const store = (0, import_react12.useContext)(VizijContext);
1947
2070
  if (!store) throw new Error("Missing VizijProvider in the tree");
1948
- (0, import_react11.useEffect)(() => {
2071
+ (0, import_react12.useEffect)(() => {
1949
2072
  const initialValue = selector(store.getState());
1950
2073
  listener(initialValue);
1951
2074
  return store.subscribe(selector, listener);
@@ -1953,17 +2076,17 @@ function useVizijStoreSubscription(selector, listener) {
1953
2076
  }
1954
2077
 
1955
2078
  // src/hooks/use-vizij-store-setter.ts
1956
- var import_react12 = require("react");
2079
+ var import_react13 = require("react");
1957
2080
  function useVizijStoreSetter() {
1958
- const store = (0, import_react12.useContext)(VizijContext);
2081
+ const store = (0, import_react13.useContext)(VizijContext);
1959
2082
  if (!store) throw new Error("Missing VizijProvider in the tree");
1960
2083
  return store.setState;
1961
2084
  }
1962
2085
 
1963
2086
  // src/hooks/use-vizij-store-getter.ts
1964
- var import_react13 = require("react");
2087
+ var import_react14 = require("react");
1965
2088
  function useVizijStoreGetter() {
1966
- const store = (0, import_react13.useContext)(VizijContext);
2089
+ const store = (0, import_react14.useContext)(VizijContext);
1967
2090
  if (!store) throw new Error("Missing VizijProvider in the tree");
1968
2091
  return store.getState;
1969
2092
  }
@@ -1973,7 +2096,7 @@ var THREE5 = __toESM(require("three"));
1973
2096
  var import_three_stdlib = require("three-stdlib");
1974
2097
 
1975
2098
  // src/functions/gltf-loading/traverse-three.ts
1976
- var import_react15 = require("react");
2099
+ var import_react16 = require("react");
1977
2100
  var THREE4 = __toESM(require("three"));
1978
2101
 
1979
2102
  // src/functions/gltf-loading/map-features.ts
@@ -1999,19 +2122,19 @@ function mapFeatures(features) {
1999
2122
  }
2000
2123
 
2001
2124
  // src/functions/gltf-loading/import-scene.ts
2002
- var import_three4 = require("three");
2125
+ var import_three5 = require("three");
2003
2126
 
2004
2127
  // src/functions/gltf-loading/import-group.ts
2005
- var import_three3 = require("three");
2128
+ var import_three4 = require("three");
2006
2129
 
2007
2130
  // src/functions/util.ts
2008
- var import_react14 = require("react");
2131
+ var import_react15 = require("react");
2009
2132
  function namespaceArrayToRefs(namespaces) {
2010
- return namespaces.reduce((acc, ns) => ({ ...acc, [ns]: (0, import_react14.createRef)() }), {});
2133
+ return namespaces.reduce((acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }), {});
2011
2134
  }
2012
2135
 
2013
2136
  // src/functions/gltf-loading/import-mesh.ts
2014
- var import_three2 = require("three");
2137
+ var import_three3 = require("three");
2015
2138
 
2016
2139
  // src/functions/gltf-loading/import-geometry.ts
2017
2140
  function sanitizeMorphKey(name, fallbackIndex, used) {
@@ -2051,7 +2174,7 @@ function importGeometry(geometry, mesh) {
2051
2174
  type: "number",
2052
2175
  default: mesh.morphTargetInfluences?.[index] ?? 0,
2053
2176
  constraints: {
2054
- min: 0,
2177
+ min: -1,
2055
2178
  max: 1
2056
2179
  },
2057
2180
  pub: {
@@ -2067,7 +2190,7 @@ function importGeometry(geometry, mesh) {
2067
2190
  }
2068
2191
 
2069
2192
  // src/functions/gltf-loading/import-mesh.ts
2070
- import_three2.Object3D.DEFAULT_UP.set(0, 0, 1);
2193
+ import_three3.Object3D.DEFAULT_UP.set(0, 0, 1);
2071
2194
  function importMesh(mesh, namespaces, colorLookup) {
2072
2195
  let world = {};
2073
2196
  let animatables = {};
@@ -2226,7 +2349,7 @@ function getShapeMaterial(mesh, useEmissive) {
2226
2349
  }
2227
2350
 
2228
2351
  // src/functions/gltf-loading/import-group.ts
2229
- import_three3.Object3D.DEFAULT_UP.set(0, 0, 1);
2352
+ import_three4.Object3D.DEFAULT_UP.set(0, 0, 1);
2230
2353
  function importGroup(group, namespaces, colorLookup, rootBounds) {
2231
2354
  let world = {};
2232
2355
  let animatables = {};
@@ -2314,7 +2437,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
2314
2437
  }
2315
2438
 
2316
2439
  // src/functions/gltf-loading/import-scene.ts
2317
- import_three4.Object3D.DEFAULT_UP.set(0, 0, 1);
2440
+ import_three5.Object3D.DEFAULT_UP.set(0, 0, 1);
2318
2441
  function importScene(scene, namespaces, rootBounds) {
2319
2442
  let world = {};
2320
2443
  let animatables = {};
@@ -2356,7 +2479,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
2356
2479
  loadedData = {
2357
2480
  ...data,
2358
2481
  refs: namespaces.reduce(
2359
- (acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }),
2482
+ (acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
2360
2483
  {}
2361
2484
  )
2362
2485
  };
@@ -2371,7 +2494,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
2371
2494
  ...data,
2372
2495
  geometry: child.geometry,
2373
2496
  refs: namespaces.reduce(
2374
- (acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }),
2497
+ (acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
2375
2498
  {}
2376
2499
  )
2377
2500
  };
@@ -2385,7 +2508,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
2385
2508
  loadedData = {
2386
2509
  ...data,
2387
2510
  refs: namespaces.reduce(
2388
- (acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }),
2511
+ (acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
2389
2512
  {}
2390
2513
  )
2391
2514
  };
@@ -2399,7 +2522,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
2399
2522
  loadedData = {
2400
2523
  ...data,
2401
2524
  refs: namespaces.reduce(
2402
- (acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }),
2525
+ (acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
2403
2526
  {}
2404
2527
  )
2405
2528
  };
@@ -2585,9 +2708,10 @@ function deriveRootBounds(group) {
2585
2708
  }
2586
2709
 
2587
2710
  // src/functions/vizij-bundle.ts
2711
+ var import_utils7 = require("@vizij/utils");
2588
2712
  var BUNDLE_KEYS = ["VIZIJ_bundle"];
2589
2713
  function cloneBundle(value) {
2590
- return JSON.parse(JSON.stringify(value));
2714
+ return (0, import_utils7.cloneDeepSafe)(value);
2591
2715
  }
2592
2716
  function readExtensionValue(extensionContainer) {
2593
2717
  for (const key of BUNDLE_KEYS) {
@@ -2685,6 +2809,7 @@ function applyVizijBundle(object, bundle) {
2685
2809
  }
2686
2810
 
2687
2811
  // src/functions/gltf-loading/extract-animations.ts
2812
+ var import_utils8 = require("@vizij/utils");
2688
2813
  var CHANNEL_PATH_TO_TRACK_PROPERTY = {
2689
2814
  translation: "position",
2690
2815
  rotation: "quaternion",
@@ -2700,7 +2825,7 @@ function clonePlainObject(value) {
2700
2825
  if (!value) {
2701
2826
  return void 0;
2702
2827
  }
2703
- return JSON.parse(JSON.stringify(value));
2828
+ return (0, import_utils8.cloneDeepSafe)(value);
2704
2829
  }
2705
2830
  function inferValueSize(valueType) {
2706
2831
  switch (valueType) {
package/dist/index.mjs CHANGED
@@ -1,19 +1,10 @@
1
1
  // src/vizij.tsx
2
- import {
3
- Suspense,
4
- memo as memo6,
5
- useContext as useContext3,
6
- useEffect as useEffect6
7
- } from "react";
2
+ import { Suspense, memo as memo6, useContext as useContext3, useEffect as useEffect7 } from "react";
8
3
  import { ErrorBoundary } from "react-error-boundary";
9
- import {
10
- Object3D as Object3D4,
11
- SRGBColorSpace,
12
- NoToneMapping
13
- } from "three";
4
+ import { Object3D as Object3D4, SRGBColorSpace, NoToneMapping } from "three";
14
5
  import { Canvas, useThree } from "@react-three/fiber";
15
6
  import { Line as Line3, OrthographicCamera, Text } from "@react-three/drei";
16
- import { useShallow as useShallow6 } from "zustand/react/shallow";
7
+ import { useShallow as useShallow7 } from "zustand/react/shallow";
17
8
 
18
9
  // src/renderables/renderable.tsx
19
10
  import { memo as memo5, useMemo as useMemo5 } from "react";
@@ -35,13 +26,7 @@ function useVizijStore(selector) {
35
26
  }
36
27
 
37
28
  // src/renderables/group.tsx
38
- import {
39
- memo,
40
- useCallback,
41
- useEffect as useEffect2,
42
- useRef,
43
- useMemo
44
- } from "react";
29
+ import { memo, useCallback, useEffect as useEffect2, useRef, useMemo } from "react";
45
30
  import * as THREE from "three";
46
31
  import { useShallow } from "zustand/react/shallow";
47
32
  import {
@@ -138,7 +123,7 @@ function InnerRenderedGroup({
138
123
  namespace,
139
124
  chain
140
125
  }) {
141
- const ref = useRef();
126
+ const ref = useRef(null);
142
127
  const group = useVizijStore(useShallow((state) => state.world[id]));
143
128
  const refIsNull = !group.refs[namespace]?.current;
144
129
  const animatables = useVizijStore(useShallow((state) => state.animatables));
@@ -249,13 +234,7 @@ function InnerRenderedGroup({
249
234
  var RenderedGroup = memo(InnerRenderedGroup);
250
235
 
251
236
  // src/renderables/ellipse.tsx
252
- import {
253
- memo as memo2,
254
- useCallback as useCallback2,
255
- useEffect as useEffect3,
256
- useRef as useRef2,
257
- useMemo as useMemo2
258
- } from "react";
237
+ import { memo as memo2, useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useMemo as useMemo2 } from "react";
259
238
  import { useShallow as useShallow2 } from "zustand/react/shallow";
260
239
  import {
261
240
  instanceOfRawNumber as instanceOfRawNumber2,
@@ -272,9 +251,11 @@ function InnerRenderedEllipse({
272
251
  namespace,
273
252
  chain
274
253
  }) {
275
- const ellipseRef = useRef2();
276
- const materialRef = useRef2();
277
- const lineRef = useRef2();
254
+ const ellipseRef = useRef2(null);
255
+ const materialRef = useRef2(
256
+ null
257
+ );
258
+ const lineRef = useRef2(null);
278
259
  const strokeOffsetRef = useRef2(0);
279
260
  const strokeWidthRef = useRef2(0);
280
261
  const onElementClick = useVizijStore(
@@ -547,13 +528,7 @@ var showLine = (ellipse) => {
547
528
  };
548
529
 
549
530
  // src/renderables/rectangle.tsx
550
- import {
551
- memo as memo3,
552
- useCallback as useCallback3,
553
- useEffect as useEffect4,
554
- useRef as useRef3,
555
- useMemo as useMemo3
556
- } from "react";
531
+ import { memo as memo3, useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useMemo as useMemo3 } from "react";
557
532
  import { useShallow as useShallow3 } from "zustand/react/shallow";
558
533
  import {
559
534
  instanceOfRawNumber as instanceOfRawNumber3,
@@ -570,9 +545,11 @@ function InnerRenderedRectangle({
570
545
  namespace,
571
546
  chain
572
547
  }) {
573
- const rectangleRef = useRef3();
574
- const materialRef = useRef3();
575
- const lineRef = useRef3();
548
+ const rectangleRef = useRef3(null);
549
+ const materialRef = useRef3(
550
+ null
551
+ );
552
+ const lineRef = useRef3(null);
576
553
  const strokeOffsetRef = useRef3(0);
577
554
  const strokeWidthRef = useRef3(0);
578
555
  const onElementClick = useVizijStore(
@@ -846,13 +823,7 @@ var showLine2 = (rectangle) => {
846
823
  };
847
824
 
848
825
  // src/renderables/shape.tsx
849
- import {
850
- memo as memo4,
851
- useCallback as useCallback4,
852
- useRef as useRef4,
853
- useMemo as useMemo4,
854
- useEffect as useEffect5
855
- } from "react";
826
+ import { memo as memo4, useCallback as useCallback4, useRef as useRef4, useMemo as useMemo4, useEffect as useEffect5 } from "react";
856
827
  import * as THREE2 from "three";
857
828
  import { useShallow as useShallow4 } from "zustand/react/shallow";
858
829
  import {
@@ -869,8 +840,8 @@ function InnerRenderedShape({
869
840
  namespace,
870
841
  chain
871
842
  }) {
872
- const refGroup = useRef4();
873
- const ref = useRef4();
843
+ const refGroup = useRef4(null);
844
+ const ref = useRef4(null);
874
845
  const shape = useVizijStore(useShallow4((state) => state.world[id]));
875
846
  const refs = useVizijStore(
876
847
  useShallow4((state) => state.world[id].refs)
@@ -911,7 +882,7 @@ function InnerRenderedShape({
911
882
  }),
912
883
  [shape, animatableValues, selectionData]
913
884
  );
914
- const material = useRef4();
885
+ const material = useRef4(null);
915
886
  const morphTargetSettings = useMemo4(() => {
916
887
  if (shape.morphTargets) {
917
888
  const dictionary = shape.morphTargets.reduce(
@@ -1557,6 +1528,19 @@ var VizijSlice = (set, get) => ({
1557
1528
  })
1558
1529
  );
1559
1530
  },
1531
+ setValues: (writes = []) => {
1532
+ if (writes.length === 0) {
1533
+ return;
1534
+ }
1535
+ set(
1536
+ produce((state) => {
1537
+ writes.forEach(({ id, namespace, value }) => {
1538
+ const lookupId = getLookup2(namespace, id);
1539
+ state.values.set(lookupId, value);
1540
+ });
1541
+ })
1542
+ );
1543
+ },
1560
1544
  setWorldElementName: (id, value) => {
1561
1545
  set(
1562
1546
  produce((state) => {
@@ -1751,8 +1735,117 @@ var createVizijStore = (initial) => create()(
1751
1735
  }))
1752
1736
  );
1753
1737
 
1738
+ // src/effects/selection-glow-effect.tsx
1739
+ import { Fragment as Fragment4, useEffect as useEffect6, useMemo as useMemo6, useRef as useRef5 } from "react";
1740
+ import { useFrame } from "@react-three/fiber";
1741
+ import { useShallow as useShallow6 } from "zustand/react/shallow";
1742
+ import {
1743
+ AdditiveBlending,
1744
+ Color,
1745
+ EdgesGeometry,
1746
+ LineBasicMaterial,
1747
+ Matrix4,
1748
+ Quaternion,
1749
+ Vector3
1750
+ } from "three";
1751
+ import { jsx as jsx6 } from "react/jsx-runtime";
1752
+ function SelectionGlowEffect({
1753
+ enabled = false,
1754
+ color = "#ff1010ff",
1755
+ opacity = 0.9,
1756
+ thresholdAngle = 2
1757
+ }) {
1758
+ const selections = useVizijStore(
1759
+ useShallow6(
1760
+ (state) => enabled ? state.elementSelection ?? [] : []
1761
+ )
1762
+ );
1763
+ if (!enabled || selections.length === 0) {
1764
+ return null;
1765
+ }
1766
+ return /* @__PURE__ */ jsx6(Fragment4, { children: selections.map((selection) => /* @__PURE__ */ jsx6(
1767
+ SelectionOutline,
1768
+ {
1769
+ selection,
1770
+ color: selection.color ?? color,
1771
+ opacity,
1772
+ thresholdAngle
1773
+ },
1774
+ `${selection.namespace}:${selection.id}`
1775
+ )) });
1776
+ }
1777
+ function SelectionOutline({
1778
+ selection,
1779
+ color,
1780
+ opacity,
1781
+ thresholdAngle
1782
+ }) {
1783
+ const target = useVizijStore(
1784
+ useShallow6((state) => {
1785
+ const entry = state.world[selection.id];
1786
+ const ref = entry?.refs?.[selection.namespace];
1787
+ const geometry = entry?.geometry ?? null;
1788
+ return { ref, geometry };
1789
+ })
1790
+ );
1791
+ const sourceRef = target.ref;
1792
+ const edgesGeometry = useMemo6(() => {
1793
+ if (!target.geometry) return null;
1794
+ const edges = new EdgesGeometry(target.geometry, thresholdAngle);
1795
+ return edges;
1796
+ }, [target.geometry, thresholdAngle]);
1797
+ useEffect6(() => () => edgesGeometry?.dispose(), [edgesGeometry]);
1798
+ const material = useMemo6(() => {
1799
+ const mat = new LineBasicMaterial({
1800
+ color: new Color(color),
1801
+ transparent: true,
1802
+ opacity,
1803
+ blending: AdditiveBlending,
1804
+ depthTest: false,
1805
+ depthWrite: false,
1806
+ toneMapped: false
1807
+ });
1808
+ return mat;
1809
+ }, [color, opacity]);
1810
+ useEffect6(() => () => material.dispose(), [material]);
1811
+ const lineRef = useRef5(null);
1812
+ useFrame(() => {
1813
+ const source = sourceRef?.current;
1814
+ const line = lineRef.current;
1815
+ if (!source || !line) return;
1816
+ copyWorldTransform(source, line);
1817
+ line.visible = source.visible;
1818
+ });
1819
+ if (!sourceRef || !edgesGeometry) {
1820
+ return null;
1821
+ }
1822
+ return /* @__PURE__ */ jsx6(
1823
+ "lineSegments",
1824
+ {
1825
+ ref: lineRef,
1826
+ geometry: edgesGeometry,
1827
+ material,
1828
+ frustumCulled: false,
1829
+ renderOrder: 1e3
1830
+ }
1831
+ );
1832
+ }
1833
+ var tempMatrix = new Matrix4();
1834
+ var tempPosition = new Vector3();
1835
+ var tempQuaternion = new Quaternion();
1836
+ var tempScale = new Vector3();
1837
+ function copyWorldTransform(source, target) {
1838
+ source.updateWorldMatrix(true, false);
1839
+ tempMatrix.copy(source.matrixWorld);
1840
+ tempMatrix.decompose(tempPosition, tempQuaternion, tempScale);
1841
+ target.position.copy(tempPosition);
1842
+ target.quaternion.copy(tempQuaternion);
1843
+ target.scale.copy(tempScale);
1844
+ target.updateMatrix();
1845
+ }
1846
+
1754
1847
  // src/vizij.tsx
1755
- import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1848
+ import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
1756
1849
  Object3D4.DEFAULT_UP.set(0, 0, 1);
1757
1850
  function Vizij({
1758
1851
  style,
@@ -1760,11 +1853,12 @@ function Vizij({
1760
1853
  rootId,
1761
1854
  namespace = "default",
1762
1855
  showSafeArea = false,
1856
+ showSelectionGlow = false,
1763
1857
  onPointerMissed
1764
1858
  }) {
1765
1859
  const ctx = useContext3(VizijContext);
1766
1860
  if (ctx) {
1767
- return /* @__PURE__ */ jsx6(
1861
+ return /* @__PURE__ */ jsx7(
1768
1862
  Canvas,
1769
1863
  {
1770
1864
  shadows: false,
@@ -1776,18 +1870,19 @@ function Vizij({
1776
1870
  toneMapping: NoToneMapping,
1777
1871
  antialias: true
1778
1872
  },
1779
- children: /* @__PURE__ */ jsx6(
1873
+ children: /* @__PURE__ */ jsx7(
1780
1874
  MemoizedInnerVizij,
1781
1875
  {
1782
1876
  rootId,
1783
1877
  namespace,
1784
- showSafeArea
1878
+ showSafeArea,
1879
+ showSelectionGlow
1785
1880
  }
1786
1881
  )
1787
1882
  }
1788
1883
  );
1789
1884
  } else {
1790
- return /* @__PURE__ */ jsx6(VizijContext.Provider, { value: useDefaultVizijStore, children: /* @__PURE__ */ jsx6(
1885
+ return /* @__PURE__ */ jsx7(VizijContext.Provider, { value: useDefaultVizijStore, children: /* @__PURE__ */ jsx7(
1791
1886
  Canvas,
1792
1887
  {
1793
1888
  style,
@@ -1798,12 +1893,13 @@ function Vizij({
1798
1893
  toneMapping: NoToneMapping,
1799
1894
  antialias: true
1800
1895
  },
1801
- children: /* @__PURE__ */ jsx6(
1896
+ children: /* @__PURE__ */ jsx7(
1802
1897
  MemoizedInnerVizij,
1803
1898
  {
1804
1899
  rootId,
1805
1900
  namespace,
1806
- showSafeArea
1901
+ showSafeArea,
1902
+ showSelectionGlow
1807
1903
  }
1808
1904
  )
1809
1905
  }
@@ -1814,15 +1910,16 @@ function InnerVizij({
1814
1910
  rootId,
1815
1911
  namespace = "default",
1816
1912
  container,
1817
- showSafeArea
1913
+ showSafeArea,
1914
+ showSelectionGlow
1818
1915
  }) {
1819
1916
  const sceneParentSizing = container ? {
1820
1917
  width: container.width * container.resolution,
1821
1918
  height: container.height * container.resolution
1822
1919
  } : void 0;
1823
- return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1824
- /* @__PURE__ */ jsx6("ambientLight", { intensity: Math.PI / 2 }),
1825
- /* @__PURE__ */ jsx6(
1920
+ return /* @__PURE__ */ jsxs4(Fragment5, { children: [
1921
+ /* @__PURE__ */ jsx7("ambientLight", { intensity: Math.PI / 2 }),
1922
+ /* @__PURE__ */ jsx7(
1826
1923
  OrthographicCamera,
1827
1924
  {
1828
1925
  makeDefault: true,
@@ -1831,7 +1928,7 @@ function InnerVizij({
1831
1928
  far: 101
1832
1929
  }
1833
1930
  ),
1834
- /* @__PURE__ */ jsx6(Suspense, { fallback: null, children: /* @__PURE__ */ jsx6(
1931
+ /* @__PURE__ */ jsx7(Suspense, { fallback: null, children: /* @__PURE__ */ jsx7(
1835
1932
  World,
1836
1933
  {
1837
1934
  rootId,
@@ -1839,7 +1936,8 @@ function InnerVizij({
1839
1936
  parentSizing: sceneParentSizing
1840
1937
  }
1841
1938
  ) }),
1842
- showSafeArea && /* @__PURE__ */ jsx6(SafeAreaRenderer, { rootId })
1939
+ showSelectionGlow && /* @__PURE__ */ jsx7(SelectionGlowEffect, { enabled: true }),
1940
+ showSafeArea && /* @__PURE__ */ jsx7(SafeAreaRenderer, { rootId })
1843
1941
  ] });
1844
1942
  }
1845
1943
  var MemoizedInnerVizij = memo6(InnerVizij);
@@ -1849,7 +1947,7 @@ function InnerWorld({
1849
1947
  parentSizing
1850
1948
  }) {
1851
1949
  const [present, rootBounds] = useVizijStore(
1852
- useShallow6((state) => {
1950
+ useShallow7((state) => {
1853
1951
  const group = state.world[rootId];
1854
1952
  const bounds = group?.rootBounds ?? defaultRootBounds;
1855
1953
  return [group !== void 0, bounds];
@@ -1859,7 +1957,7 @@ function InnerWorld({
1859
1957
  camera: state.camera,
1860
1958
  size: state.size
1861
1959
  }));
1862
- useEffect6(() => {
1960
+ useEffect7(() => {
1863
1961
  const width = rootBounds.size.x;
1864
1962
  const height = rootBounds.size.y;
1865
1963
  if (camera && parentSizing === void 0 && camera.isOrthographicCamera) {
@@ -1888,8 +1986,8 @@ function InnerWorld({
1888
1986
  }
1889
1987
  }, [rootBounds, camera, parentSizing, size]);
1890
1988
  return /* @__PURE__ */ jsxs4(ErrorBoundary, { fallback: null, children: [
1891
- present && /* @__PURE__ */ jsx6(Renderable, { id: rootId, namespace, chain: [] }),
1892
- !present && /* @__PURE__ */ jsx6(
1989
+ present && /* @__PURE__ */ jsx7(Renderable, { id: rootId, namespace, chain: [] }),
1990
+ !present && /* @__PURE__ */ jsx7(
1893
1991
  Text,
1894
1992
  {
1895
1993
  position: [0, 0, 0],
@@ -1912,7 +2010,7 @@ function SafeAreaRenderer({ rootId }) {
1912
2010
  const right = rootBounds.center.x + rootBounds.size.x / 2;
1913
2011
  const top = rootBounds.center.y + rootBounds.size.y / 2;
1914
2012
  const bottom = rootBounds.center.y - rootBounds.size.y / 2;
1915
- return /* @__PURE__ */ jsx6(
2013
+ return /* @__PURE__ */ jsx7(
1916
2014
  Line3,
1917
2015
  {
1918
2016
  points: [
@@ -1943,11 +2041,11 @@ var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
1943
2041
  })(ShapeMaterial || {});
1944
2042
 
1945
2043
  // src/hooks/use-vizij-store-subscription.ts
1946
- import { useContext as useContext4, useEffect as useEffect7 } from "react";
2044
+ import { useContext as useContext4, useEffect as useEffect8 } from "react";
1947
2045
  function useVizijStoreSubscription(selector, listener) {
1948
2046
  const store = useContext4(VizijContext);
1949
2047
  if (!store) throw new Error("Missing VizijProvider in the tree");
1950
- useEffect7(() => {
2048
+ useEffect8(() => {
1951
2049
  const initialValue = selector(store.getState());
1952
2050
  listener(initialValue);
1953
2051
  return store.subscribe(selector, listener);
@@ -2013,9 +2111,7 @@ function namespaceArrayToRefs(namespaces) {
2013
2111
  }
2014
2112
 
2015
2113
  // src/functions/gltf-loading/import-mesh.ts
2016
- import {
2017
- Object3D as Object3D5
2018
- } from "three";
2114
+ import { Object3D as Object3D5 } from "three";
2019
2115
 
2020
2116
  // src/functions/gltf-loading/import-geometry.ts
2021
2117
  function sanitizeMorphKey(name, fallbackIndex, used) {
@@ -2055,7 +2151,7 @@ function importGeometry(geometry, mesh) {
2055
2151
  type: "number",
2056
2152
  default: mesh.morphTargetInfluences?.[index] ?? 0,
2057
2153
  constraints: {
2058
- min: 0,
2154
+ min: -1,
2059
2155
  max: 1
2060
2156
  },
2061
2157
  pub: {
@@ -2589,9 +2685,10 @@ function deriveRootBounds(group) {
2589
2685
  }
2590
2686
 
2591
2687
  // src/functions/vizij-bundle.ts
2688
+ import { cloneDeepSafe } from "@vizij/utils";
2592
2689
  var BUNDLE_KEYS = ["VIZIJ_bundle"];
2593
2690
  function cloneBundle(value) {
2594
- return JSON.parse(JSON.stringify(value));
2691
+ return cloneDeepSafe(value);
2595
2692
  }
2596
2693
  function readExtensionValue(extensionContainer) {
2597
2694
  for (const key of BUNDLE_KEYS) {
@@ -2689,6 +2786,7 @@ function applyVizijBundle(object, bundle) {
2689
2786
  }
2690
2787
 
2691
2788
  // src/functions/gltf-loading/extract-animations.ts
2789
+ import { cloneDeepSafe as cloneDeepSafe2 } from "@vizij/utils";
2692
2790
  var CHANNEL_PATH_TO_TRACK_PROPERTY = {
2693
2791
  translation: "position",
2694
2792
  rotation: "quaternion",
@@ -2704,7 +2802,7 @@ function clonePlainObject(value) {
2704
2802
  if (!value) {
2705
2803
  return void 0;
2706
2804
  }
2707
- return JSON.parse(JSON.stringify(value));
2805
+ return cloneDeepSafe2(value);
2708
2806
  }
2709
2807
  function inferValueSize(valueType) {
2710
2808
  switch (valueType) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vizij/render",
3
3
  "description": "Higher-level visualization and interaction components for robot and ai faces.",
4
- "version": "0.0.7",
4
+ "version": "0.1.0",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@vizij/utils": "0.0.3",
27
+ "@vizij/utils": "0.1.0",
28
28
  "clsx": "^2.1.1",
29
29
  "deep-equal": "^2.2.3",
30
30
  "immer": "^10.0.3",
@@ -33,8 +33,8 @@
33
33
  "three-stdlib": "^2.35.13"
34
34
  },
35
35
  "peerDependencies": {
36
- "@react-three/drei": "^9.115.0",
37
- "@react-three/fiber": "^8.17.10",
36
+ "@react-three/drei": "^10.7.7",
37
+ "@react-three/fiber": "^9.5.0",
38
38
  "react": ">=18",
39
39
  "react-dom": ">=18",
40
40
  "tailwindcss": "^4.1.3",
@@ -42,15 +42,15 @@
42
42
  "zustand": "^5.0.2"
43
43
  },
44
44
  "devDependencies": {
45
- "@react-three/drei": "^9.115.0",
46
- "@react-three/fiber": "^8.17.10",
45
+ "@react-three/drei": "^10.7.7",
46
+ "@react-three/fiber": "^9.5.0",
47
47
  "@types/deep-equal": "^1.0.4",
48
48
  "@types/lodash": "^4.17.4",
49
- "@types/react": "^18.3.1",
49
+ "@types/react": "^19.2.7",
50
50
  "@types/three": "^0.170.0",
51
51
  "@size-limit/file": "^11.2.0",
52
- "react": "^18.3.1",
53
- "react-dom": "^18.3.1",
52
+ "react": "^19.2.3",
53
+ "react-dom": "^19.2.3",
54
54
  "size-limit": "^11.1.7",
55
55
  "three": "^0.170.0",
56
56
  "zustand": "^5.0.2",