@tscircuit/3d-viewer 0.0.571 → 0.0.572

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 (2) hide show
  1. package/dist/index.js +131 -100
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14432,7 +14432,7 @@ var require_browser = __commonJS({
14432
14432
  });
14433
14433
 
14434
14434
  // src/CadViewer.tsx
14435
- import { useState as useState37, useCallback as useCallback23, useRef as useRef28, useEffect as useEffect47 } from "react";
14435
+ import { useState as useState37, useCallback as useCallback23, useRef as useRef29, useEffect as useEffect46 } from "react";
14436
14436
  import * as THREE44 from "three";
14437
14437
 
14438
14438
  // src/CadViewerJscad.tsx
@@ -32398,7 +32398,7 @@ import * as THREE20 from "three";
32398
32398
  // package.json
32399
32399
  var package_default = {
32400
32400
  name: "@tscircuit/3d-viewer",
32401
- version: "0.0.570",
32401
+ version: "0.0.571",
32402
32402
  main: "./dist/index.js",
32403
32403
  module: "./dist/index.js",
32404
32404
  type: "module",
@@ -33027,25 +33027,35 @@ import { useEffect as useEffect15, useMemo as useMemo13 } from "react";
33027
33027
  import * as THREE17 from "three";
33028
33028
  var Lights = () => {
33029
33029
  const { scene } = useThree();
33030
- const ambientLight = useMemo13(
33031
- () => new THREE17.AmbientLight(16777215, Math.PI / 2),
33032
- []
33033
- );
33034
- const pointLight = useMemo13(() => {
33035
- const light = new THREE17.PointLight(16777215, Math.PI / 4);
33036
- light.position.set(-10, -10, 10);
33037
- light.decay = 0;
33038
- return light;
33030
+ const lightRig = useMemo13(() => {
33031
+ const rig = new THREE17.Group();
33032
+ rig.name = "cad-viewer-light-rig";
33033
+ const ambientLight = new THREE17.AmbientLight(16777215, 0.18);
33034
+ ambientLight.name = "cad-viewer-soft-ambient";
33035
+ rig.add(ambientLight);
33036
+ const hemisphereLight = new THREE17.HemisphereLight(14543103, 2040093, 0.45);
33037
+ hemisphereLight.name = "cad-viewer-hemisphere";
33038
+ rig.add(hemisphereLight);
33039
+ const addDirectionalLight = (name, color, intensity, position) => {
33040
+ const light = new THREE17.DirectionalLight(color, intensity);
33041
+ light.name = name;
33042
+ light.position.set(...position);
33043
+ light.target.position.set(0, 0, 0);
33044
+ rig.add(light);
33045
+ rig.add(light.target);
33046
+ };
33047
+ addDirectionalLight("cad-viewer-key-light", 16773343, 2.4, [8, -10, 12]);
33048
+ addDirectionalLight("cad-viewer-fill-light", 14543103, 0.7, [-10, 8, 5]);
33049
+ addDirectionalLight("cad-viewer-rim-light", 16777215, 1.1, [-4, 10, 8]);
33050
+ return rig;
33039
33051
  }, []);
33040
33052
  useEffect15(() => {
33041
33053
  if (!scene) return;
33042
- scene.add(ambientLight);
33043
- scene.add(pointLight);
33054
+ scene.add(lightRig);
33044
33055
  return () => {
33045
- scene.remove(ambientLight);
33046
- scene.remove(pointLight);
33056
+ scene.remove(lightRig);
33047
33057
  };
33048
- }, [scene, ambientLight, pointLight]);
33058
+ }, [scene, lightRig]);
33049
33059
  return null;
33050
33060
  };
33051
33061
 
@@ -39533,7 +39543,7 @@ function composeContextScopes(...scopes) {
39533
39543
  }
39534
39544
 
39535
39545
  // node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
39536
- import * as React15 from "react";
39546
+ import * as React16 from "react";
39537
39547
 
39538
39548
  // node_modules/@radix-ui/react-use-layout-effect/dist/index.mjs
39539
39549
  import * as React14 from "react";
@@ -39542,7 +39552,32 @@ var useLayoutEffect2 = globalThis?.document ? React14.useLayoutEffect : () => {
39542
39552
 
39543
39553
  // node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
39544
39554
  import * as React22 from "react";
39545
- var useInsertionEffect = React15[" useInsertionEffect ".trim().toString()] || useLayoutEffect2;
39555
+
39556
+ // node_modules/@radix-ui/react-use-effect-event/dist/index.mjs
39557
+ import * as React15 from "react";
39558
+ var useReactEffectEvent = React15[" useEffectEvent ".trim().toString()];
39559
+ var useReactInsertionEffect = React15[" useInsertionEffect ".trim().toString()];
39560
+ function useEffectEvent(callback) {
39561
+ if (typeof useReactEffectEvent === "function") {
39562
+ return useReactEffectEvent(callback);
39563
+ }
39564
+ const ref = React15.useRef(() => {
39565
+ throw new Error("Cannot call an event handler while rendering.");
39566
+ });
39567
+ if (typeof useReactInsertionEffect === "function") {
39568
+ useReactInsertionEffect(() => {
39569
+ ref.current = callback;
39570
+ });
39571
+ } else {
39572
+ useLayoutEffect2(() => {
39573
+ ref.current = callback;
39574
+ });
39575
+ }
39576
+ return React15.useMemo(() => ((...args) => ref.current?.(...args)), []);
39577
+ }
39578
+
39579
+ // node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs
39580
+ var useInsertionEffect = React16[" useInsertionEffect ".trim().toString()] || useLayoutEffect2;
39546
39581
  function useControllableState({
39547
39582
  prop,
39548
39583
  defaultProp,
@@ -39557,8 +39592,8 @@ function useControllableState({
39557
39592
  const isControlled = prop !== void 0;
39558
39593
  const value = isControlled ? prop : uncontrolledProp;
39559
39594
  if (true) {
39560
- const isControlledRef = React15.useRef(prop !== void 0);
39561
- React15.useEffect(() => {
39595
+ const isControlledRef = React16.useRef(prop !== void 0);
39596
+ React16.useEffect(() => {
39562
39597
  const wasControlled = isControlledRef.current;
39563
39598
  if (wasControlled !== isControlled) {
39564
39599
  const from = wasControlled ? "controlled" : "uncontrolled";
@@ -39570,7 +39605,7 @@ function useControllableState({
39570
39605
  isControlledRef.current = isControlled;
39571
39606
  }, [isControlled, caller]);
39572
39607
  }
39573
- const setValue = React15.useCallback(
39608
+ const setValue = React16.useCallback(
39574
39609
  (nextValue) => {
39575
39610
  if (isControlled) {
39576
39611
  const value2 = isFunction(nextValue) ? nextValue(prop) : nextValue;
@@ -39589,13 +39624,13 @@ function useUncontrolledState({
39589
39624
  defaultProp,
39590
39625
  onChange
39591
39626
  }) {
39592
- const [value, setValue] = React15.useState(defaultProp);
39593
- const prevValueRef = React15.useRef(value);
39594
- const onChangeRef = React15.useRef(onChange);
39627
+ const [value, setValue] = React16.useState(defaultProp);
39628
+ const prevValueRef = React16.useRef(value);
39629
+ const onChangeRef = React16.useRef(onChange);
39595
39630
  useInsertionEffect(() => {
39596
39631
  onChangeRef.current = onChange;
39597
39632
  }, [onChange]);
39598
- React15.useEffect(() => {
39633
+ React16.useEffect(() => {
39599
39634
  if (prevValueRef.current !== value) {
39600
39635
  onChangeRef.current?.(value);
39601
39636
  prevValueRef.current = value;
@@ -39608,14 +39643,14 @@ function isFunction(value) {
39608
39643
  }
39609
39644
 
39610
39645
  // node_modules/@radix-ui/react-primitive/dist/index.mjs
39611
- import * as React17 from "react";
39646
+ import * as React18 from "react";
39612
39647
  import * as ReactDOM2 from "react-dom";
39613
39648
 
39614
39649
  // node_modules/@radix-ui/react-slot/dist/index.mjs
39615
- import * as React16 from "react";
39650
+ import * as React17 from "react";
39616
39651
  // @__NO_SIDE_EFFECTS__
39617
39652
  function createSlot(ownerName) {
39618
- const Slot2 = React16.forwardRef((props, forwardedRef) => {
39653
+ const Slot2 = React17.forwardRef((props, forwardedRef) => {
39619
39654
  let { children, ...slotProps } = props;
39620
39655
  let slottableElement = null;
39621
39656
  let hasSlottable = false;
@@ -39623,7 +39658,7 @@ function createSlot(ownerName) {
39623
39658
  if (isLazyComponent(children) && typeof use === "function") {
39624
39659
  children = use(children._payload);
39625
39660
  }
39626
- React16.Children.forEach(children, (maybeSlottable) => {
39661
+ React17.Children.forEach(children, (maybeSlottable) => {
39627
39662
  if (isSlottable(maybeSlottable)) {
39628
39663
  hasSlottable = true;
39629
39664
  const slottable = maybeSlottable;
@@ -39638,13 +39673,13 @@ function createSlot(ownerName) {
39638
39673
  }
39639
39674
  });
39640
39675
  if (slottableElement) {
39641
- slottableElement = React16.cloneElement(slottableElement, void 0, newChildren);
39676
+ slottableElement = React17.cloneElement(slottableElement, void 0, newChildren);
39642
39677
  } else if (
39643
39678
  // A `Slottable` was found but it didn't resolve to a single element (e.g.
39644
39679
  // it wrapped multiple elements, text, or a render-prop `child` that
39645
39680
  // wasn't an element). Don't fall back to treating the `Slottable` wrapper
39646
39681
  // itself as the slot target — throw a descriptive error below instead.
39647
- !hasSlottable && React16.Children.count(children) === 1 && React16.isValidElement(children)
39682
+ !hasSlottable && React17.Children.count(children) === 1 && React17.isValidElement(children)
39648
39683
  ) {
39649
39684
  slottableElement = children;
39650
39685
  }
@@ -39659,10 +39694,10 @@ function createSlot(ownerName) {
39659
39694
  return children;
39660
39695
  }
39661
39696
  const mergedProps = mergeProps(slotProps, slottableElement.props ?? {});
39662
- if (slottableElement.type !== React16.Fragment) {
39697
+ if (slottableElement.type !== React17.Fragment) {
39663
39698
  mergedProps.ref = forwardedRef ? composedRef : slottableElementRef;
39664
39699
  }
39665
- return React16.cloneElement(slottableElement, mergedProps);
39700
+ return React17.cloneElement(slottableElement, mergedProps);
39666
39701
  });
39667
39702
  Slot2.displayName = `${ownerName}.Slot`;
39668
39703
  return Slot2;
@@ -39671,10 +39706,10 @@ var SLOTTABLE_IDENTIFIER = /* @__PURE__ */ Symbol.for("radix.slottable");
39671
39706
  var getSlottableElementFromSlottable = (slottable, child) => {
39672
39707
  if ("child" in slottable.props) {
39673
39708
  const child2 = slottable.props.child;
39674
- if (!React16.isValidElement(child2)) return null;
39675
- return React16.cloneElement(child2, void 0, slottable.props.children(child2.props.children));
39709
+ if (!React17.isValidElement(child2)) return null;
39710
+ return React17.cloneElement(child2, void 0, slottable.props.children(child2.props.children));
39676
39711
  }
39677
- return React16.isValidElement(child) ? child : null;
39712
+ return React17.isValidElement(child) ? child : null;
39678
39713
  };
39679
39714
  function mergeProps(slotProps, childProps) {
39680
39715
  const overrideProps = { ...childProps };
@@ -39714,7 +39749,7 @@ function getElementRef(element) {
39714
39749
  return element.props.ref || element.ref;
39715
39750
  }
39716
39751
  function isSlottable(child) {
39717
- return React16.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
39752
+ return React17.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
39718
39753
  }
39719
39754
  var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
39720
39755
  function isLazyComponent(element) {
@@ -39729,7 +39764,7 @@ var createSlotError = (ownerName) => {
39729
39764
  var createSlottableError = (ownerName) => {
39730
39765
  return `${ownerName} failed to slot onto its \`Slottable\`. Expected \`Slottable\` to receive a single React element child.`;
39731
39766
  };
39732
- var use = React16[" use ".trim().toString()];
39767
+ var use = React17[" use ".trim().toString()];
39733
39768
 
39734
39769
  // node_modules/@radix-ui/react-primitive/dist/index.mjs
39735
39770
  import { jsx as jsx21 } from "react/jsx-runtime";
@@ -39754,7 +39789,7 @@ var NODES = [
39754
39789
  ];
39755
39790
  var Primitive = NODES.reduce((primitive, node) => {
39756
39791
  const Slot2 = createSlot(`Primitive.${node}`);
39757
- const Node2 = React17.forwardRef((props, forwardedRef) => {
39792
+ const Node2 = React18.forwardRef((props, forwardedRef) => {
39758
39793
  const { asChild, ...primitiveProps } = props;
39759
39794
  const Comp = asChild ? Slot2 : node;
39760
39795
  if (typeof window !== "undefined") {
@@ -39773,7 +39808,7 @@ function dispatchDiscreteCustomEvent(target, event) {
39773
39808
  import * as React42 from "react";
39774
39809
 
39775
39810
  // node_modules/@radix-ui/react-collection/dist/index.mjs
39776
- import * as React18 from "react";
39811
+ import * as React19 from "react";
39777
39812
  import { jsx as jsx22 } from "react/jsx-runtime";
39778
39813
  import * as React23 from "react";
39779
39814
  import { jsx as jsx23 } from "react/jsx-runtime";
@@ -39786,14 +39821,14 @@ function createCollection(name) {
39786
39821
  );
39787
39822
  const CollectionProvider = (props) => {
39788
39823
  const { scope, children } = props;
39789
- const ref = React18.useRef(null);
39790
- const itemMap = React18.useRef(/* @__PURE__ */ new Map()).current;
39824
+ const ref = React19.useRef(null);
39825
+ const itemMap = React19.useRef(/* @__PURE__ */ new Map()).current;
39791
39826
  return /* @__PURE__ */ jsx22(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
39792
39827
  };
39793
39828
  CollectionProvider.displayName = PROVIDER_NAME;
39794
39829
  const COLLECTION_SLOT_NAME = name + "CollectionSlot";
39795
39830
  const CollectionSlotImpl = createSlot(COLLECTION_SLOT_NAME);
39796
- const CollectionSlot = React18.forwardRef(
39831
+ const CollectionSlot = React19.forwardRef(
39797
39832
  (props, forwardedRef) => {
39798
39833
  const { scope, children } = props;
39799
39834
  const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
@@ -39805,13 +39840,13 @@ function createCollection(name) {
39805
39840
  const ITEM_SLOT_NAME = name + "CollectionItemSlot";
39806
39841
  const ITEM_DATA_ATTR = "data-radix-collection-item";
39807
39842
  const CollectionItemSlotImpl = createSlot(ITEM_SLOT_NAME);
39808
- const CollectionItemSlot = React18.forwardRef(
39843
+ const CollectionItemSlot = React19.forwardRef(
39809
39844
  (props, forwardedRef) => {
39810
39845
  const { scope, children, ...itemData } = props;
39811
- const ref = React18.useRef(null);
39846
+ const ref = React19.useRef(null);
39812
39847
  const composedRefs = useComposedRefs(forwardedRef, ref);
39813
39848
  const context = useCollectionContext(ITEM_SLOT_NAME, scope);
39814
- React18.useEffect(() => {
39849
+ React19.useEffect(() => {
39815
39850
  context.itemMap.set(ref, { ref, ...itemData });
39816
39851
  return () => void context.itemMap.delete(ref);
39817
39852
  });
@@ -39821,7 +39856,7 @@ function createCollection(name) {
39821
39856
  CollectionItemSlot.displayName = ITEM_SLOT_NAME;
39822
39857
  function useCollection3(scope) {
39823
39858
  const context = useCollectionContext(name + "CollectionConsumer", scope);
39824
- const getItems = React18.useCallback(() => {
39859
+ const getItems = React19.useCallback(() => {
39825
39860
  const collectionNode = context.collectionRef.current;
39826
39861
  if (!collectionNode) return [];
39827
39862
  const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
@@ -39841,11 +39876,11 @@ function createCollection(name) {
39841
39876
  }
39842
39877
 
39843
39878
  // node_modules/@radix-ui/react-direction/dist/index.mjs
39844
- import * as React19 from "react";
39879
+ import * as React20 from "react";
39845
39880
  import { jsx as jsx24 } from "react/jsx-runtime";
39846
- var DirectionContext = React19.createContext(void 0);
39881
+ var DirectionContext = React20.createContext(void 0);
39847
39882
  function useDirection(localDir) {
39848
- const globalDir = React19.useContext(DirectionContext);
39883
+ const globalDir = React20.useContext(DirectionContext);
39849
39884
  return localDir || globalDir || "ltr";
39850
39885
  }
39851
39886
 
@@ -39853,28 +39888,13 @@ function useDirection(localDir) {
39853
39888
  import * as React24 from "react";
39854
39889
 
39855
39890
  // node_modules/@radix-ui/react-use-callback-ref/dist/index.mjs
39856
- import * as React20 from "react";
39891
+ import * as React21 from "react";
39857
39892
  function useCallbackRef(callback) {
39858
- const callbackRef = React20.useRef(callback);
39859
- React20.useEffect(() => {
39893
+ const callbackRef = React21.useRef(callback);
39894
+ React21.useEffect(() => {
39860
39895
  callbackRef.current = callback;
39861
39896
  });
39862
- return React20.useMemo(() => ((...args) => callbackRef.current?.(...args)), []);
39863
- }
39864
-
39865
- // node_modules/@radix-ui/react-use-escape-keydown/dist/index.mjs
39866
- import * as React21 from "react";
39867
- function useEscapeKeydown(onEscapeKeyDownProp, ownerDocument = globalThis?.document) {
39868
- const onEscapeKeyDown = useCallbackRef(onEscapeKeyDownProp);
39869
- React21.useEffect(() => {
39870
- const handleKeyDown = (event) => {
39871
- if (event.key === "Escape") {
39872
- onEscapeKeyDown(event);
39873
- }
39874
- };
39875
- ownerDocument.addEventListener("keydown", handleKeyDown, { capture: true });
39876
- return () => ownerDocument.removeEventListener("keydown", handleKeyDown, { capture: true });
39877
- }, [onEscapeKeyDown, ownerDocument]);
39897
+ return React21.useMemo(() => ((...args) => callbackRef.current?.(...args)), []);
39878
39898
  }
39879
39899
 
39880
39900
  // node_modules/@radix-ui/react-dismissable-layer/dist/index.mjs
@@ -39911,7 +39931,7 @@ var DismissableLayer = React24.forwardRef(
39911
39931
  const [node, setNode] = React24.useState(null);
39912
39932
  const ownerDocument = node?.ownerDocument ?? globalThis?.document;
39913
39933
  const [, force] = React24.useState({});
39914
- const composedRefs = useComposedRefs(forwardedRef, (node2) => setNode(node2));
39934
+ const composedRefs = useComposedRefs(forwardedRef, setNode);
39915
39935
  const layers = Array.from(context.layers);
39916
39936
  const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1);
39917
39937
  const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled);
@@ -39951,15 +39971,24 @@ var DismissableLayer = React24.forwardRef(
39951
39971
  onInteractOutside?.(event);
39952
39972
  if (!event.defaultPrevented) onDismiss?.();
39953
39973
  }, ownerDocument);
39954
- useEscapeKeydown((event) => {
39955
- const isHighestLayer = index2 === context.layers.size - 1;
39956
- if (!isHighestLayer) return;
39974
+ const isHighestLayer = node ? index2 === layers.length - 1 : false;
39975
+ const handleKeyDown = useEffectEvent((event) => {
39976
+ if (event.key !== "Escape") {
39977
+ return;
39978
+ }
39957
39979
  onEscapeKeyDown?.(event);
39958
39980
  if (!event.defaultPrevented && onDismiss) {
39959
39981
  event.preventDefault();
39960
39982
  onDismiss();
39961
39983
  }
39962
- }, ownerDocument);
39984
+ });
39985
+ React24.useEffect(() => {
39986
+ if (!isHighestLayer) {
39987
+ return;
39988
+ }
39989
+ ownerDocument.addEventListener("keydown", handleKeyDown, { capture: true });
39990
+ return () => ownerDocument.removeEventListener("keydown", handleKeyDown, { capture: true });
39991
+ }, [ownerDocument, isHighestLayer]);
39963
39992
  React24.useEffect(() => {
39964
39993
  if (!node) return;
39965
39994
  if (disableOutsidePointerEvents) {
@@ -40235,7 +40264,7 @@ var FocusScope = React26.forwardRef((props, forwardedRef) => {
40235
40264
  const onMountAutoFocus = useCallbackRef(onMountAutoFocusProp);
40236
40265
  const onUnmountAutoFocus = useCallbackRef(onUnmountAutoFocusProp);
40237
40266
  const lastFocusedElementRef = React26.useRef(null);
40238
- const composedRefs = useComposedRefs(forwardedRef, (node) => setContainer(node));
40267
+ const composedRefs = useComposedRefs(forwardedRef, setContainer);
40239
40268
  const focusScope = React26.useRef({
40240
40269
  paused: false,
40241
40270
  pause() {
@@ -42509,7 +42538,7 @@ var PopperContent = React31.forwardRef(
42509
42538
  } = props;
42510
42539
  const context = usePopperContext(CONTENT_NAME, __scopePopper);
42511
42540
  const [content, setContent] = React31.useState(null);
42512
- const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
42541
+ const composedRefs = useComposedRefs(forwardedRef, setContent);
42513
42542
  const [arrow4, setArrow] = React31.useState(null);
42514
42543
  const arrowSize = useSize(arrow4);
42515
42544
  const arrowWidth = arrowSize?.width ?? 0;
@@ -44599,6 +44628,7 @@ var MenuSubTrigger = React42.forwardRef(
44599
44628
  onPointerGraceIntentChange(null);
44600
44629
  };
44601
44630
  }, [pointerGraceTimerRef, onPointerGraceIntentChange]);
44631
+ const composedRefs = useComposedRefs(forwardedRef, subContext.onTriggerChange);
44602
44632
  return /* @__PURE__ */ jsx31(MenuAnchor, { asChild: true, ...scope, children: /* @__PURE__ */ jsx31(
44603
44633
  MenuItemImpl,
44604
44634
  {
@@ -44608,7 +44638,7 @@ var MenuSubTrigger = React42.forwardRef(
44608
44638
  "aria-controls": context.open ? subContext.contentId : void 0,
44609
44639
  "data-state": getOpenState(context.open),
44610
44640
  ...props,
44611
- ref: composeRefs(forwardedRef, subContext.onTriggerChange),
44641
+ ref: composedRefs,
44612
44642
  onClick: (event) => {
44613
44643
  props.onClick?.(event);
44614
44644
  if (props.disabled || event.defaultPrevented) return;
@@ -44785,7 +44815,7 @@ var Root32 = Menu;
44785
44815
  var Anchor2 = MenuAnchor;
44786
44816
  var Portal2 = MenuPortal;
44787
44817
  var Content2 = MenuContent;
44788
- var Group6 = MenuGroup;
44818
+ var Group7 = MenuGroup;
44789
44819
  var Label = MenuLabel;
44790
44820
  var Item2 = MenuItem;
44791
44821
  var CheckboxItem = MenuCheckboxItem;
@@ -44847,6 +44877,7 @@ var DropdownMenuTrigger = React43.forwardRef(
44847
44877
  const { __scopeDropdownMenu, disabled = false, ...triggerProps } = props;
44848
44878
  const context = useDropdownMenuContext(TRIGGER_NAME, __scopeDropdownMenu);
44849
44879
  const menuScope = useMenuScope(__scopeDropdownMenu);
44880
+ const composedRefs = useComposedRefs(forwardedRef, context.triggerRef);
44850
44881
  return /* @__PURE__ */ jsx32(Anchor2, { asChild: true, ...menuScope, children: /* @__PURE__ */ jsx32(
44851
44882
  Primitive.button,
44852
44883
  {
@@ -44859,7 +44890,7 @@ var DropdownMenuTrigger = React43.forwardRef(
44859
44890
  "data-disabled": disabled ? "" : void 0,
44860
44891
  disabled,
44861
44892
  ...triggerProps,
44862
- ref: composeRefs(forwardedRef, context.triggerRef),
44893
+ ref: composedRefs,
44863
44894
  onPointerDown: composeEventHandlers(props.onPointerDown, (event) => {
44864
44895
  if (!disabled && event.button === 0 && event.ctrlKey === false) {
44865
44896
  context.onOpenToggle();
@@ -44931,7 +44962,7 @@ var DropdownMenuGroup = React43.forwardRef(
44931
44962
  (props, forwardedRef) => {
44932
44963
  const { __scopeDropdownMenu, ...groupProps } = props;
44933
44964
  const menuScope = useMenuScope(__scopeDropdownMenu);
44934
- return /* @__PURE__ */ jsx32(Group6, { ...menuScope, ...groupProps, ref: forwardedRef });
44965
+ return /* @__PURE__ */ jsx32(Group7, { ...menuScope, ...groupProps, ref: forwardedRef });
44935
44966
  }
44936
44967
  );
44937
44968
  DropdownMenuGroup.displayName = GROUP_NAME3;
@@ -45783,16 +45814,16 @@ var ContextMenu = ({
45783
45814
  };
45784
45815
 
45785
45816
  // src/components/KeyboardShortcutsDialog.tsx
45786
- import { useEffect as useEffect46, useMemo as useMemo29, useRef as useRef27, useState as useState36 } from "react";
45817
+ import { useEffect as useEffect45, useMemo as useMemo30, useRef as useRef28, useState as useState36 } from "react";
45787
45818
  import { jsx as jsx36, jsxs as jsxs10 } from "react/jsx-runtime";
45788
45819
  var KeyboardShortcutsDialog = ({
45789
45820
  open,
45790
45821
  onClose
45791
45822
  }) => {
45792
45823
  const [query, setQuery] = useState36("");
45793
- const inputRef = useRef27(null);
45824
+ const inputRef = useRef28(null);
45794
45825
  const hotkeys = useHotkeyRegistry();
45795
- useEffect46(() => {
45826
+ useEffect45(() => {
45796
45827
  if (!open) return void 0;
45797
45828
  const handleKeyDown = (event) => {
45798
45829
  if (event.key === "Escape") {
@@ -45803,14 +45834,14 @@ var KeyboardShortcutsDialog = ({
45803
45834
  window.addEventListener("keydown", handleKeyDown);
45804
45835
  return () => window.removeEventListener("keydown", handleKeyDown);
45805
45836
  }, [open, onClose]);
45806
- useEffect46(() => {
45837
+ useEffect45(() => {
45807
45838
  if (open) {
45808
45839
  setTimeout(() => {
45809
45840
  inputRef.current?.focus();
45810
45841
  }, 0);
45811
45842
  }
45812
45843
  }, [open]);
45813
- const filteredHotkeys = useMemo29(() => {
45844
+ const filteredHotkeys = useMemo30(() => {
45814
45845
  const normalizedQuery = query.trim().toLowerCase();
45815
45846
  if (!normalizedQuery) {
45816
45847
  return hotkeys;
@@ -45986,7 +46017,7 @@ var CadViewerInner = (props) => {
45986
46017
  const stored = window.localStorage.getItem("cadViewerEngine");
45987
46018
  return stored === "jscad" || stored === "manifold" ? stored : "manifold";
45988
46019
  });
45989
- const containerRef = useRef28(null);
46020
+ const containerRef = useRef29(null);
45990
46021
  const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState37(false);
45991
46022
  const [autoRotate, setAutoRotate] = useState37(() => {
45992
46023
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
@@ -46000,7 +46031,7 @@ var CadViewerInner = (props) => {
46000
46031
  const { cameraType, setCameraType } = useCameraController();
46001
46032
  const { visibility, setLayerVisibility } = useLayerVisibility();
46002
46033
  const { showToast } = useToast();
46003
- const cameraControllerRef = useRef28(null);
46034
+ const cameraControllerRef = useRef29(null);
46004
46035
  const externalCameraControllerReady = props.onCameraControllerReady;
46005
46036
  const {
46006
46037
  menuVisible,
@@ -46009,10 +46040,10 @@ var CadViewerInner = (props) => {
46009
46040
  contextMenuEventHandlers,
46010
46041
  setMenuVisible
46011
46042
  } = useContextMenu({ containerRef });
46012
- const autoRotateUserToggledRef = useRef28(autoRotateUserToggled);
46043
+ const autoRotateUserToggledRef = useRef29(autoRotateUserToggled);
46013
46044
  autoRotateUserToggledRef.current = autoRotateUserToggled;
46014
- const isAnimatingRef = useRef28(false);
46015
- const lastPresetSelectTime = useRef28(0);
46045
+ const isAnimatingRef = useRef29(false);
46046
+ const lastPresetSelectTime = useRef29(0);
46016
46047
  const PRESET_COOLDOWN = 1e3;
46017
46048
  const handleUserInteraction = useCallback23(() => {
46018
46049
  if (isAnimatingRef.current || Date.now() - lastPresetSelectTime.current < PRESET_COOLDOWN) {
@@ -46107,24 +46138,24 @@ var CadViewerInner = (props) => {
46107
46138
  description: "Toggle translucent components"
46108
46139
  }
46109
46140
  );
46110
- useEffect47(() => {
46141
+ useEffect46(() => {
46111
46142
  if (containerRef.current) {
46112
46143
  registerHotkeyViewer(containerRef.current);
46113
46144
  }
46114
46145
  }, []);
46115
- useEffect47(() => {
46146
+ useEffect46(() => {
46116
46147
  window.localStorage.setItem("cadViewerEngine", engine);
46117
46148
  }, [engine]);
46118
- useEffect47(() => {
46149
+ useEffect46(() => {
46119
46150
  window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
46120
46151
  }, [autoRotate]);
46121
- useEffect47(() => {
46152
+ useEffect46(() => {
46122
46153
  window.localStorage.setItem(
46123
46154
  "cadViewerAutoRotateUserToggled",
46124
46155
  String(autoRotateUserToggled)
46125
46156
  );
46126
46157
  }, [autoRotateUserToggled]);
46127
- useEffect47(() => {
46158
+ useEffect46(() => {
46128
46159
  window.localStorage.setItem("cadViewerCameraType", cameraType);
46129
46160
  }, [cameraType]);
46130
46161
  const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
@@ -46525,10 +46556,10 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
46525
46556
 
46526
46557
  // src/hooks/exporter/gltf.ts
46527
46558
  import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
46528
- import { useEffect as useEffect48, useState as useState38, useMemo as useMemo30, useCallback as useCallback24 } from "react";
46559
+ import { useEffect as useEffect47, useState as useState38, useMemo as useMemo31, useCallback as useCallback24 } from "react";
46529
46560
  function useSaveGltfAs(options = {}) {
46530
46561
  const parse2 = useParser(options);
46531
- const link = useMemo30(() => document.createElement("a"), []);
46562
+ const link = useMemo31(() => document.createElement("a"), []);
46532
46563
  const saveAs = async (filename) => {
46533
46564
  const name = filename ?? options.filename ?? "";
46534
46565
  if (options.binary == null) options.binary = name.endsWith(".glb");
@@ -46538,7 +46569,7 @@ function useSaveGltfAs(options = {}) {
46538
46569
  link.dispatchEvent(new MouseEvent("click"));
46539
46570
  URL.revokeObjectURL(url);
46540
46571
  };
46541
- useEffect48(
46572
+ useEffect47(
46542
46573
  () => () => {
46543
46574
  link.remove();
46544
46575
  instance = null;
@@ -46559,11 +46590,11 @@ function useExportGltfUrl(options = {}) {
46559
46590
  (instance) => parse2(instance).then(setUrl).catch(setError),
46560
46591
  []
46561
46592
  );
46562
- useEffect48(() => () => URL.revokeObjectURL(url), [url]);
46593
+ useEffect47(() => () => URL.revokeObjectURL(url), [url]);
46563
46594
  return [ref, url, error];
46564
46595
  }
46565
46596
  function useParser(options = {}) {
46566
- const exporter = useMemo30(() => new GLTFExporter3(), []);
46597
+ const exporter = useMemo31(() => new GLTFExporter3(), []);
46567
46598
  return (instance) => {
46568
46599
  const { promise, resolve, reject } = Promise.withResolvers();
46569
46600
  exporter.parse(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.571",
3
+ "version": "0.0.572",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",