door_models 5.0.3 → 5.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -2,12 +2,14 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var react = require('react');
5
+ var React = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var csg = require('@react-three/csg');
8
8
  var three = require('@react-spring/three');
9
9
  var THREE = require('three');
10
10
 
11
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+
11
13
  function _interopNamespace(e) {
12
14
  if (e && e.__esModule) return e;
13
15
  var n = Object.create(null);
@@ -26,6 +28,7 @@ function _interopNamespace(e) {
26
28
  return Object.freeze(n);
27
29
  }
28
30
 
31
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
29
32
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
30
33
 
31
34
  function _defineProperty(e, r, t) {
@@ -93,21 +96,21 @@ function _toPropertyKey(t) {
93
96
  }
94
97
 
95
98
  const _excluded = ["doorDepth"];
96
- const ConfiguratorContext = /*#__PURE__*/react.createContext(undefined);
99
+ const ConfiguratorContext = /*#__PURE__*/React.createContext(undefined);
97
100
  const ConfiguratorProvider = _ref => {
98
101
  let {
99
102
  children,
100
103
  initialIs2D = false
101
104
  } = _ref;
102
- const [is2D, setIs2D] = react.useState(initialIs2D);
103
- const [isPlaneVisible, setIsPlaneVisible] = react.useState(false);
104
- const [isFrameVisible, setIsFrameVisible] = react.useState(true);
105
- const [cpid, setCpid] = react.useState("");
106
- const [totalHeight, setTotalHeight] = react.useState(2700);
107
- const [totalWidth, setTotalWidth] = react.useState(974);
108
- const [glassVisible, setGlassVisible] = react.useState(false);
109
- const [glassDepth, setGlassDepth] = react.useState(8);
110
- const [door, setDoor] = react.useState({
105
+ const [is2D, setIs2D] = React.useState(initialIs2D);
106
+ const [isPlaneVisible, setIsPlaneVisible] = React.useState(false);
107
+ const [isFrameVisible, setIsFrameVisible] = React.useState(true);
108
+ const [cpid, setCpid] = React.useState("");
109
+ const [totalHeight, setTotalHeight] = React.useState(2700);
110
+ const [totalWidth, setTotalWidth] = React.useState(974);
111
+ const [glassVisible, setGlassVisible] = React.useState(false);
112
+ const [glassDepth, setGlassDepth] = React.useState(8);
113
+ const [door, setDoor] = React.useState({
111
114
  doorMaterial: "door_material",
112
115
  doorWidth: 0,
113
116
  doorHeight: 0,
@@ -115,7 +118,7 @@ const ConfiguratorProvider = _ref => {
115
118
  doorPivot: "left",
116
119
  doorOpening: "out"
117
120
  });
118
- const [doorFrame, setDoorFrame] = react.useState({
121
+ const [doorFrame, setDoorFrame] = React.useState({
119
122
  frameMaterial: "doorFrame_material",
120
123
  doorStopMaterial: "doorStop_material",
121
124
  gasketMaterial: "gasket_material",
@@ -136,18 +139,18 @@ const ConfiguratorProvider = _ref => {
136
139
  secondDoorStopDepth: 30,
137
140
  secondDoorStopOffset: 13
138
141
  });
139
- const [interiorFanlight, setInteriorFanlight] = react.useState({
142
+ const [interiorFanlight, setInteriorFanlight] = React.useState({
140
143
  visible: false,
141
144
  height: 300,
142
145
  material: "interiorFanlight_material"
143
146
  });
144
- const [exteriorFanlight, setExteriorFanlight] = react.useState({
147
+ const [exteriorFanlight, setExteriorFanlight] = React.useState({
145
148
  visible: false,
146
149
  height: 300,
147
150
  depth: 60,
148
151
  material: "exteriorFanlight_material"
149
152
  });
150
- const [occulus, setOcculus] = react.useState({
153
+ const [occulus, setOcculus] = React.useState({
151
154
  visible: false,
152
155
  infillVisible: true,
153
156
  x1: 150,
@@ -157,49 +160,49 @@ const ConfiguratorProvider = _ref => {
157
160
  material: "infill_material",
158
161
  depth: 20
159
162
  });
160
- const [frontCoverPanel, setFrontCoverPanel] = react.useState({
163
+ const [frontCoverPanel, setFrontCoverPanel] = React.useState({
161
164
  visible: false,
162
165
  width: 73,
163
166
  height: 2200,
164
167
  depth: 12,
165
168
  material: "front_cover_material"
166
169
  });
167
- const [backCoverPanel, setBackCoverPanel] = react.useState({
170
+ const [backCoverPanel, setBackCoverPanel] = React.useState({
168
171
  visible: false,
169
172
  width: 73,
170
173
  height: 2200,
171
174
  depth: 12,
172
175
  material: "back_cover_material"
173
176
  });
174
- const [glass, setGlass] = react.useState({
177
+ const [glass, setGlass] = React.useState({
175
178
  visible: false,
176
179
  material: "infill_material",
177
180
  depth: 20
178
181
  });
179
- const [frameType, setFrameType] = react.useState("AF20_40");
180
- const [bodyType, setBodyType] = react.useState("40");
181
- const [exteriorFanlightType, setExteriorFanlightType] = react.useState("WPFL");
182
- const [testDoorMaterial, setTestDoorMaterial] = react.useState("brown");
183
- const [testFrameMaterial, setTestFrameMaterial] = react.useState("black");
184
- const [testGasketMaterial, setTestGasketMaterial] = react.useState("darkgrey");
185
- const [testInteriorFanlightMaterial, setTestInteriorFanlightMaterial] = react.useState("grey");
186
- const [testExteriorFanlightMaterial, setTestExteriorFanlightMaterial] = react.useState("metal");
187
- const [testOcculusInfillMaterial, setTestOcculusInfillMaterial] = react.useState("glass");
188
- const [testGlassInfillMaterial, setTestGlassInfillMaterial] = react.useState("glass");
189
- const [testDoorStopMaterial, setTestDoorStopMaterial] = react.useState("black");
190
- const [testHingeMaterial, setTestHingeMaterial] = react.useState("metal");
191
- const [testFrontCoverPanelMaterial, setTestFrontCoverPanelMaterial] = react.useState("aluminum");
192
- const [testBackCoverPanelMaterial, setTestBackCoverPanelMaterial] = react.useState("aluminum");
182
+ const [frameType, setFrameType] = React.useState("AF20_40");
183
+ const [bodyType, setBodyType] = React.useState("40");
184
+ const [exteriorFanlightType, setExteriorFanlightType] = React.useState("WPFL");
185
+ const [testDoorMaterial, setTestDoorMaterial] = React.useState("brown");
186
+ const [testFrameMaterial, setTestFrameMaterial] = React.useState("black");
187
+ const [testGasketMaterial, setTestGasketMaterial] = React.useState("darkgrey");
188
+ const [testInteriorFanlightMaterial, setTestInteriorFanlightMaterial] = React.useState("grey");
189
+ const [testExteriorFanlightMaterial, setTestExteriorFanlightMaterial] = React.useState("metal");
190
+ const [testOcculusInfillMaterial, setTestOcculusInfillMaterial] = React.useState("glass");
191
+ const [testGlassInfillMaterial, setTestGlassInfillMaterial] = React.useState("glass");
192
+ const [testDoorStopMaterial, setTestDoorStopMaterial] = React.useState("black");
193
+ const [testHingeMaterial, setTestHingeMaterial] = React.useState("metal");
194
+ const [testFrontCoverPanelMaterial, setTestFrontCoverPanelMaterial] = React.useState("aluminum");
195
+ const [testBackCoverPanelMaterial, setTestBackCoverPanelMaterial] = React.useState("aluminum");
193
196
 
194
197
  //
195
- const [parseMessage, setParseMessage] = react.useState({
198
+ const [parseMessage, setParseMessage] = React.useState({
196
199
  type: "",
197
200
  text: ""
198
201
  });
199
- react.useEffect(() => {
202
+ React.useEffect(() => {
200
203
  setIs2D(initialIs2D);
201
204
  }, [initialIs2D]);
202
- const handleParseCpid = react.useCallback(cpidToParse => {
205
+ const handleParseCpid = React.useCallback(cpidToParse => {
203
206
  const showMessage = function (text) {
204
207
  let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "error";
205
208
  setParseMessage({
@@ -307,7 +310,7 @@ const ConfiguratorProvider = _ref => {
307
310
  }, [setBodyType, setExteriorFanlight, setExteriorFanlightType, setFrameType, setInteriorFanlight, setOcculus]);
308
311
 
309
312
  // --- BodyType Effect ---
310
- react.useEffect(() => {
313
+ React.useEffect(() => {
311
314
  let newDoorDepth = 40;
312
315
  let newMaterial = "brown";
313
316
  switch (bodyType) {
@@ -334,7 +337,7 @@ const ConfiguratorProvider = _ref => {
334
337
  }, [bodyType]);
335
338
 
336
339
  // --- FrameType Effect ---
337
- react.useEffect(() => {
340
+ React.useEffect(() => {
338
341
  setIsFrameVisible(frameType !== "NOF");
339
342
  setGlassVisible(false);
340
343
  let newSettings = {};
@@ -595,7 +598,7 @@ const ConfiguratorProvider = _ref => {
595
598
  }, [frameType]);
596
599
 
597
600
  // --- Exterior Fanlight Logic ---
598
- react.useEffect(() => {
601
+ React.useEffect(() => {
599
602
  if (!exteriorFanlight.visible) return;
600
603
  switch (exteriorFanlightType) {
601
604
  case "WPFL":
@@ -604,13 +607,13 @@ const ConfiguratorProvider = _ref => {
604
607
  }));
605
608
  setTestExteriorFanlightMaterial("metal");
606
609
  break;
607
- case "ALDGL":
610
+ case "ALDGFL":
608
611
  setExteriorFanlight(prev => _objectSpread2(_objectSpread2({}, prev), {}, {
609
612
  depth: doorFrame.frameDepth
610
613
  }));
611
614
  setTestExteriorFanlightMaterial("glass");
612
615
  break;
613
- case "ALSGL":
616
+ case "ALSGFL":
614
617
  setExteriorFanlight(prev => _objectSpread2(_objectSpread2({}, prev), {}, {
615
618
  depth: 40
616
619
  }));
@@ -618,7 +621,12 @@ const ConfiguratorProvider = _ref => {
618
621
  break;
619
622
  }
620
623
  }, [exteriorFanlight.visible, exteriorFanlightType, doorFrame.frameDepth, setTestExteriorFanlightMaterial, setExteriorFanlight]);
621
- react.useEffect(() => {
624
+ React.useEffect(() => {
625
+ setOcculus(prevOcculus => _objectSpread2(_objectSpread2({}, prevOcculus), {}, {
626
+ depth: door.theDoorDepth
627
+ }));
628
+ }, [door.theDoorDepth]);
629
+ React.useEffect(() => {
622
630
  const topThkValue = parseInt(doorFrame.topThk) || 0;
623
631
  const exteriorFanlightHeight = exteriorFanlight.visible ? exteriorFanlight.height : 0;
624
632
  const newDoorHeight = totalHeight - topThkValue - exteriorFanlightHeight;
@@ -626,7 +634,7 @@ const ConfiguratorProvider = _ref => {
626
634
  doorHeight: newDoorHeight > 0 ? newDoorHeight : 0
627
635
  }));
628
636
  }, [totalHeight, doorFrame.topThk, exteriorFanlight.visible, exteriorFanlight.height]);
629
- react.useEffect(() => {
637
+ React.useEffect(() => {
630
638
  const sidesThkValue = parseInt(doorFrame.sidesThk) || 0;
631
639
  const newDoorWidth = totalWidth - sidesThkValue * 2;
632
640
  setDoor(prevDoor => _objectSpread2(_objectSpread2({}, prevDoor), {}, {
@@ -701,7 +709,7 @@ const ConfiguratorProvider = _ref => {
701
709
  });
702
710
  };
703
711
  const useConfigurator = () => {
704
- const context = react.useContext(ConfiguratorContext);
712
+ const context = React.useContext(ConfiguratorContext);
705
713
  if (!context) {
706
714
  throw new Error("useConfigurator must be used within a ConfiguratorProvider");
707
715
  }
@@ -747,9 +755,22 @@ const availableMaterials = {
747
755
  opacity: 0.7
748
756
  }),
749
757
  aluminum: new THREE__namespace.MeshStandardMaterial({
750
- color: "#dcdcdc",
751
- metalness: 1.0,
752
- roughness: 0.3
758
+ color: "#abb0aa",
759
+ metalness: 0.8,
760
+ roughness: 0.5,
761
+ envMapIntensity: 1.2
762
+ }),
763
+ aluminumBrighter: new THREE__namespace.MeshStandardMaterial({
764
+ color: "#cdcdcd",
765
+ metalness: 0.8,
766
+ roughness: 0.5,
767
+ envMapIntensity: 1.2
768
+ }),
769
+ aluminumExtraBrighter: new THREE__namespace.MeshStandardMaterial({
770
+ color: "#ececec",
771
+ metalness: 0.8,
772
+ roughness: 0.5,
773
+ envMapIntensity: 1.2
753
774
  }),
754
775
  silver: new THREE__namespace.MeshStandardMaterial({
755
776
  color: "#c0c0c0",
@@ -770,159 +791,375 @@ const availableMaterials = {
770
791
  envMapIntensity: 1.5
771
792
  })
772
793
  };
794
+
795
+ // Custom hook for door handle calculations
773
796
  function StandardHandle(_ref) {
774
797
  let {
775
798
  position,
776
799
  doorDepthM,
777
- doorPivot
800
+ doorPivot,
801
+ frameType // 👈
778
802
  } = _ref;
779
- // --- Basic Dimensions ---
780
- const roseRadius = 0.03;
781
- const roseThickness = 0.006;
782
- const stemRadius = 0.007;
783
- const leverRadius = 0.009;
784
- const leverLength = 0.12;
785
- const metal = availableMaterials.silver;
803
+ // --- Base Dimensions ---
804
+ const roseRadius = 0.035;
805
+
806
+ // --- Thickness ---
807
+ // default 5mm, but 8mm + 1–2mm if WDG frame
808
+ const roseThickness = frameType === "WDGF_WDG100" ? 0.008 + 0.0015 // average: 9.5mm
809
+ : 0.005; // 5mm default
810
+
811
+ const handleRadius = 0.015;
812
+ const handleLength = 0.2;
813
+
814
+ // face offset based on thickness
786
815
  const faceZ = doorDepthM / 2 + roseThickness / 2;
816
+ const connectorLength = handleLength / 3;
817
+ const cornerFrontZ = faceZ + roseThickness + connectorLength;
818
+ const cornerBackZ = -faceZ - roseThickness - connectorLength;
819
+ const roseGapY = 0.07;
787
820
  return /*#__PURE__*/jsxRuntime.jsxs("group", {
788
821
  position: position,
789
- rotation: [0, 0, 0],
790
- children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
791
- "position-z": faceZ,
792
- material: metal,
793
- castShadow: true,
794
- receiveShadow: true,
795
- rotation: [Math.PI / 2, 0, 0],
796
- children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
797
- args: [roseRadius, roseRadius, roseThickness, 48]
798
- })
799
- }), /*#__PURE__*/jsxRuntime.jsxs("group", {
800
- "scale-x": doorPivot === "left" ? -1 : 1,
801
- children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
802
- "position-z": doorDepthM / 2 + stemRadius,
803
- material: metal,
822
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsxs(React__default["default"].Fragment, {
823
+ children: [frameType === "WDGF_WDG100" ?
824
+ /*#__PURE__*/
825
+ // --- Capsule rose ---
826
+ jsxRuntime.jsxs("group", {
827
+ "position-z": z,
828
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
829
+ material: availableMaterials.aluminum,
830
+ castShadow: true,
831
+ receiveShadow: true,
832
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
833
+ args: [roseRadius * 2, roseRadius * 2, roseThickness]
834
+ })
835
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
836
+ "position-y": roseRadius,
837
+ rotation: [Math.PI / 2, Math.PI / 2, 0],
838
+ material: availableMaterials.aluminum,
839
+ castShadow: true,
840
+ receiveShadow: true,
841
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
842
+ args: [roseRadius, roseRadius, roseThickness, 32, 1, false, 0, Math.PI]
843
+ })
844
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
845
+ "position-y": -roseRadius,
846
+ rotation: [-Math.PI / 2, Math.PI / 2, 0],
847
+ material: availableMaterials.aluminum,
848
+ castShadow: true,
849
+ receiveShadow: true,
850
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
851
+ args: [roseRadius, roseRadius, roseThickness, 32, 1, false, 0, Math.PI]
852
+ })
853
+ })]
854
+ }) :
855
+ /*#__PURE__*/
856
+ // --- Round rose ---
857
+ jsxRuntime.jsx("mesh", {
858
+ rotation: [Math.PI / 2, 0, 0],
859
+ "position-z": z,
860
+ material: availableMaterials.aluminum,
804
861
  castShadow: true,
805
862
  receiveShadow: true,
806
- rotation: [Math.PI / 2, 0, 0],
807
863
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
808
- args: [stemRadius, stemRadius, 0.02, 32]
864
+ args: [roseRadius, roseRadius, roseThickness, 48]
809
865
  })
810
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
811
- position: [0.06, 0, doorDepthM / 2],
812
- material: metal,
866
+ }), frameType === "WDGF_WDG100" ? /*#__PURE__*/jsxRuntime.jsxs("group", {
867
+ "position-z": z,
868
+ "position-y": -(0.08 + roseGapY),
869
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
870
+ material: availableMaterials.aluminum,
871
+ castShadow: true,
872
+ receiveShadow: true,
873
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
874
+ args: [(roseRadius - 0.008) * 2, (roseRadius - 0.008) * 2, roseThickness]
875
+ })
876
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
877
+ "position-y": roseRadius - 0.008,
878
+ rotation: [Math.PI / 2, Math.PI / 2, 0],
879
+ material: availableMaterials.aluminum,
880
+ castShadow: true,
881
+ receiveShadow: true,
882
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
883
+ args: [roseRadius - 0.008, roseRadius - 0.008, roseThickness, 32, 1, false, 0, Math.PI]
884
+ })
885
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
886
+ "position-y": -(roseRadius - 0.008),
887
+ rotation: [-Math.PI / 2, Math.PI / 2, 0],
888
+ material: availableMaterials.aluminum,
889
+ castShadow: true,
890
+ receiveShadow: true,
891
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
892
+ args: [roseRadius - 0.008, roseRadius - 0.008, roseThickness, 32, 1, false, 0, Math.PI]
893
+ })
894
+ })]
895
+ }) : /*#__PURE__*/jsxRuntime.jsx("mesh", {
896
+ rotation: [Math.PI / 2, 0, 0],
897
+ "position-z": z,
898
+ "position-y": -(0.08 + roseGapY),
899
+ material: availableMaterials.aluminum,
813
900
  castShadow: true,
814
901
  receiveShadow: true,
815
- rotation: [0, 0, Math.PI / 2],
816
902
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
817
- args: [leverRadius, leverRadius, leverLength, 32]
903
+ args: [roseRadius, roseRadius, roseThickness, 48]
818
904
  })
905
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
906
+ position: [0, -(0.08 + roseGapY),
907
+ // 👈 same Y as small rose
908
+ z + (z > 0 ? roseThickness : -roseThickness) // 👈 accounts for thickness
909
+ ],
910
+ castShadow: true,
911
+ receiveShadow: true,
912
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
913
+ rotation: [Math.PI / 2, 0, 0],
914
+ position: [0, 0.0075, 0],
915
+ material: availableMaterials.aluminumBrighter,
916
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
917
+ args: [0.01, 0.01, roseThickness, 32]
918
+ })
919
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
920
+ position: [0, -0.0075, 0],
921
+ material: availableMaterials.aluminumBrighter,
922
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
923
+ args: [0.01, 0.015, roseThickness]
924
+ })
925
+ })]
926
+ })]
927
+ }, i)), /*#__PURE__*/jsxRuntime.jsxs("group", {
928
+ scale: [doorPivot === "left" ? -1 : 1, 1, 1],
929
+ children: [/*#__PURE__*/jsxRuntime.jsxs("group", {
930
+ position: [0, 0, -0.01],
931
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
932
+ position: [0, 0, faceZ + roseThickness + connectorLength / 2],
933
+ rotation: [Math.PI / 2, 0, 0],
934
+ castShadow: true,
935
+ receiveShadow: true,
936
+ material: availableMaterials.aluminum,
937
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
938
+ args: [handleRadius, handleRadius, connectorLength, 48]
939
+ })
940
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
941
+ position: [0, 0, cornerFrontZ],
942
+ castShadow: true,
943
+ receiveShadow: true,
944
+ material: availableMaterials.aluminum,
945
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
946
+ args: [handleRadius, 32, 32]
947
+ })
948
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
949
+ position: [handleLength / 2, 0, cornerFrontZ],
950
+ rotation: [0, 0, Math.PI / 2],
951
+ castShadow: true,
952
+ receiveShadow: true,
953
+ material: availableMaterials.aluminum,
954
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
955
+ args: [handleRadius, handleRadius, handleLength, 48]
956
+ })
957
+ })]
958
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
959
+ position: [0, 0, 0.01],
960
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
961
+ position: [0, 0, -faceZ - roseThickness - connectorLength / 2],
962
+ rotation: [Math.PI / 2, 0, 0],
963
+ castShadow: true,
964
+ receiveShadow: true,
965
+ material: availableMaterials.aluminum,
966
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
967
+ args: [handleRadius, handleRadius, connectorLength, 48]
968
+ })
969
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
970
+ position: [0, 0, cornerBackZ],
971
+ castShadow: true,
972
+ receiveShadow: true,
973
+ material: availableMaterials.aluminum,
974
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
975
+ args: [handleRadius, 32, 32]
976
+ })
977
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
978
+ position: [handleLength / 2, 0, cornerBackZ],
979
+ rotation: [0, 0, Math.PI / 2],
980
+ castShadow: true,
981
+ receiveShadow: true,
982
+ material: availableMaterials.aluminum,
983
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
984
+ args: [handleRadius, handleRadius, handleLength, 48]
985
+ })
986
+ })]
819
987
  })]
820
988
  })]
821
989
  });
822
990
  }
823
- function GlassHandle(_ref2) {
991
+ const MergedPlate = _ref2 => {
992
+ let {
993
+ plateMaterial,
994
+ roseThickness,
995
+ faceZ
996
+ } = _ref2;
997
+ const geometry = React.useMemo(() => {
998
+ // Left half - sharp edges
999
+ const leftHalf = new THREE__namespace.BoxGeometry(0.05, 0.24, roseThickness);
1000
+ leftHalf.translate(-0.025, 0, 0); // Center the left half
1001
+
1002
+ const shape = new THREE__namespace.Shape();
1003
+ const width = 0.1;
1004
+ const height = 0.24;
1005
+ const radius = 0.01;
1006
+ shape.moveTo(-width / 2, -height / 2);
1007
+ shape.lineTo(-width / 2, height / 2);
1008
+ shape.lineTo(width / 2 - radius, height / 2);
1009
+ shape.absarc(width / 2 - radius, height / 2 - radius, radius, Math.PI / 2, 0, true);
1010
+ shape.lineTo(width / 2, -height / 2 + radius);
1011
+ shape.absarc(width / 2 - radius, -height / 2 + radius, radius, 0, -Math.PI / 2, true);
1012
+ shape.lineTo(-width / 2, -height / 2);
1013
+ const extrudeSettings = {
1014
+ steps: 2,
1015
+ depth: roseThickness,
1016
+ bevelEnabled: false
1017
+ };
1018
+ return new THREE__namespace.ExtrudeGeometry(shape, extrudeSettings);
1019
+ }, [roseThickness]);
1020
+ return /*#__PURE__*/jsxRuntime.jsx("group", {
1021
+ "position-z": faceZ,
1022
+ children: /*#__PURE__*/jsxRuntime.jsx("mesh", {
1023
+ geometry: geometry,
1024
+ material: plateMaterial,
1025
+ castShadow: true,
1026
+ receiveShadow: true
1027
+ })
1028
+ });
1029
+ };
1030
+ function GlassHandle(_ref3) {
824
1031
  let {
825
1032
  position,
826
1033
  doorDepthM,
827
1034
  doorPivot
828
- } = _ref2;
829
- // --- Dimensions and materials ---
830
- const roseRadius = 0.025;
1035
+ } = _ref3;
1036
+ // --- Dimensions ---
1037
+ const roseRadius = 0.035;
831
1038
  const roseThickness = 0.005;
832
- const stemRadius = 0.005;
833
- const leverRadius = 0.008;
834
- const leverLength = 0.12;
835
- const bendRadius = 0.012;
836
- const metal = availableMaterials.silver;
837
- const glassMaterial = availableMaterials.glass;
1039
+ const handleRadius = 0.015;
1040
+ const handleLength = 0.2;
838
1041
  const faceZ = doorDepthM / 2 + roseThickness / 2;
1042
+ const connectorLength = handleLength / 3;
839
1043
  return /*#__PURE__*/jsxRuntime.jsxs("group", {
840
1044
  position: position,
841
- children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
842
- rotation: [Math.PI / 2, 0, 0],
843
- "position-z": faceZ,
844
- material: metal,
845
- castShadow: true,
846
- receiveShadow: true,
847
- children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
848
- args: [roseRadius, roseRadius * 0.92, roseThickness, 48]
849
- })
850
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
851
- rotation: [Math.PI / 2, 0, 0],
852
- "position-z": -faceZ,
853
- material: metal,
854
- castShadow: true,
855
- receiveShadow: true,
856
- children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
857
- args: [roseRadius, roseRadius * 0.92, roseThickness, 48]
858
- })
859
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
860
- "position-z": faceZ + 0.001,
861
- material: glassMaterial,
862
- castShadow: true,
863
- children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
864
- args: [roseRadius * 0.4, roseRadius * 0.4, roseThickness * 0.8, 32]
865
- })
866
- }), /*#__PURE__*/jsxRuntime.jsxs("group", {
867
- "scale-x": doorPivot === "left" ? -1 : 1,
1045
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsxs(React__default["default"].Fragment, {
868
1046
  children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
869
- "position-z": doorDepthM / 2 + bendRadius,
870
- material: metal,
871
- castShadow: true,
872
- receiveShadow: true,
873
1047
  rotation: [Math.PI / 2, 0, 0],
874
- children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
875
- args: [stemRadius, stemRadius, bendRadius, 24]
876
- })
877
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
878
- position: [bendRadius, 0, doorDepthM / 2],
879
- material: metal,
1048
+ "position-z": z + (z > 0 ? roseThickness : -roseThickness) + 0.002,
1049
+ material: availableMaterials.aluminum,
880
1050
  castShadow: true,
881
1051
  receiveShadow: true,
882
- children: /*#__PURE__*/jsxRuntime.jsx("torusGeometry", {
883
- args: [bendRadius, stemRadius, 20, 48, Math.PI / 2]
884
- })
885
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
886
- position: [bendRadius + leverLength / 2, 0, doorDepthM / 2],
887
- material: metal,
888
- castShadow: true,
889
- receiveShadow: true,
890
- rotation: [0, 0, Math.PI / 2],
891
1052
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
892
- args: [leverRadius, leverRadius * 0.8, leverLength, 32]
1053
+ args: [roseRadius, roseRadius, roseThickness, 48]
893
1054
  })
894
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
895
- position: [bendRadius + leverLength, 0, doorDepthM / 2],
896
- material: metal,
1055
+ }), /*#__PURE__*/jsxRuntime.jsxs("mesh", {
1056
+ position: [0, -0.08, z + (z > 0 ? roseThickness : -roseThickness)],
897
1057
  castShadow: true,
898
- children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
899
- args: [leverRadius * 0.8, 12, 12]
900
- })
1058
+ receiveShadow: true,
1059
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1060
+ rotation: [Math.PI / 2, 0, 0],
1061
+ position: [0, 0.0075, 0],
1062
+ material: availableMaterials.aluminum,
1063
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1064
+ args: [0.01, 0.01, roseThickness, 32]
1065
+ })
1066
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1067
+ position: [0, -0.0075, 0],
1068
+ material: availableMaterials.aluminum,
1069
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
1070
+ args: [0.01, 0.015, roseThickness]
1071
+ })
1072
+ })]
1073
+ })]
1074
+ }, i)), /*#__PURE__*/jsxRuntime.jsxs("group", {
1075
+ "scale-x": doorPivot === "left" ? -1 : 1,
1076
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsx(MergedPlate, {
1077
+ faceZ: z,
1078
+ plateMaterial: availableMaterials.aluminumExtraBrighter,
1079
+ roseThickness: roseThickness
1080
+ }, "plate-".concat(i))), /*#__PURE__*/jsxRuntime.jsxs("group", {
1081
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1082
+ position: [handleLength / 2, 0, faceZ + connectorLength],
1083
+ rotation: [0, 0, Math.PI / 2],
1084
+ material: availableMaterials.aluminum,
1085
+ castShadow: true,
1086
+ receiveShadow: true,
1087
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1088
+ args: [handleRadius, handleRadius, handleLength, 48]
1089
+ })
1090
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1091
+ position: [0, 0, faceZ + connectorLength / 2],
1092
+ rotation: [Math.PI / 2, 0, 0],
1093
+ material: availableMaterials.aluminum,
1094
+ castShadow: true,
1095
+ receiveShadow: true,
1096
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1097
+ args: [handleRadius, handleRadius, connectorLength, 48]
1098
+ })
1099
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1100
+ position: [0, 0, faceZ + connectorLength],
1101
+ material: availableMaterials.aluminum,
1102
+ castShadow: true,
1103
+ receiveShadow: true,
1104
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
1105
+ args: [handleRadius, 32, 32]
1106
+ })
1107
+ })]
1108
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
1109
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1110
+ position: [handleLength / 2, 0, -(faceZ + connectorLength)],
1111
+ rotation: [0, 0, Math.PI / 2],
1112
+ material: availableMaterials.aluminum,
1113
+ castShadow: true,
1114
+ receiveShadow: true,
1115
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1116
+ args: [handleRadius, handleRadius, handleLength, 48]
1117
+ })
1118
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1119
+ position: [0, 0, -(faceZ + connectorLength / 2)],
1120
+ rotation: [Math.PI / 2, 0, 0],
1121
+ material: availableMaterials.aluminum,
1122
+ castShadow: true,
1123
+ receiveShadow: true,
1124
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1125
+ args: [handleRadius, handleRadius, connectorLength, 48]
1126
+ })
1127
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1128
+ position: [0, 0, -(faceZ + connectorLength)],
1129
+ material: availableMaterials.aluminum,
1130
+ castShadow: true,
1131
+ receiveShadow: true,
1132
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
1133
+ args: [handleRadius, 32, 32]
1134
+ })
1135
+ })]
901
1136
  })]
902
1137
  })]
903
1138
  });
904
1139
  }
905
- function DoorHandle(_ref3) {
1140
+ function DoorHandle(_ref4) {
906
1141
  let {
907
1142
  bodyType,
908
1143
  handleX,
909
1144
  handleHeightM,
910
1145
  doorDepthM,
911
1146
  doorPivot
912
- } = _ref3;
1147
+ } = _ref4;
913
1148
  const isSingleGlass = ["SG8", "SG10", "SG12"].includes(bodyType);
914
1149
  const handlePos = [handleX, handleHeightM, 0];
1150
+ const frameType = useConfigurator().frameType;
915
1151
  return isSingleGlass ? /*#__PURE__*/jsxRuntime.jsx(GlassHandle, {
916
- position: handlePos,
1152
+ position: [handleX, handleHeightM, -0.0024],
917
1153
  doorDepthM: doorDepthM,
918
1154
  doorPivot: doorPivot
919
1155
  }) : /*#__PURE__*/jsxRuntime.jsx(StandardHandle, {
920
1156
  position: handlePos,
921
1157
  doorDepthM: doorDepthM,
922
- doorPivot: doorPivot
1158
+ doorPivot: doorPivot,
1159
+ frameType: frameType
923
1160
  });
924
1161
  }
925
- function GlassHinge(_ref4) {
1162
+ function GlassHinge(_ref5) {
926
1163
  let {
927
1164
  position,
928
1165
  pivot,
@@ -930,7 +1167,7 @@ function GlassHinge(_ref4) {
930
1167
  doorDepthM,
931
1168
  material,
932
1169
  gasketMaterial
933
- } = _ref4;
1170
+ } = _ref5;
934
1171
  const plateWidth = 130 / 1000;
935
1172
  const plateHeight = 55 / 1000;
936
1173
  const plateThickness = 8 / 1000;
@@ -1006,7 +1243,7 @@ function GlassHinge(_ref4) {
1006
1243
  })]
1007
1244
  });
1008
1245
  }
1009
- function DoorStopCuts(_ref5) {
1246
+ function DoorStopCuts(_ref6) {
1010
1247
  let {
1011
1248
  visible,
1012
1249
  width,
@@ -1018,7 +1255,7 @@ function DoorStopCuts(_ref5) {
1018
1255
  glassDepthOffset = 0,
1019
1256
  material,
1020
1257
  setName
1021
- } = _ref5;
1258
+ } = _ref6;
1022
1259
  if (!visible) return null;
1023
1260
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1024
1261
  children: [/*#__PURE__*/jsxRuntime.jsx(csg.Subtraction, {
@@ -1045,10 +1282,10 @@ function DoorStopCuts(_ref5) {
1045
1282
  })]
1046
1283
  });
1047
1284
  }
1048
- function DoorModels(_ref6) {
1285
+ function DoorModels(_ref7) {
1049
1286
  let {
1050
1287
  doorName
1051
- } = _ref6;
1288
+ } = _ref7;
1052
1289
  const {
1053
1290
  is2D,
1054
1291
  totalWidth,
@@ -1081,7 +1318,7 @@ function DoorModels(_ref6) {
1081
1318
  glassDepth,
1082
1319
  handleParseCpid
1083
1320
  } = useConfigurator();
1084
- react.useEffect(() => {
1321
+ React.useEffect(() => {
1085
1322
  if (doorName) {
1086
1323
  handleParseCpid(doorName);
1087
1324
  }
@@ -1117,26 +1354,26 @@ function DoorModels(_ref6) {
1117
1354
  } = backCoverPanel;
1118
1355
 
1119
1356
  // --- Material Logic ---
1120
- const doorMaterial = react.useMemo(() => availableMaterials[testDoorMaterial] || availableMaterials[doorMaterialName] || placeholderMaterial, [testDoorMaterial, doorMaterialName]);
1121
- const frameMaterial = react.useMemo(() => availableMaterials[testFrameMaterial] || availableMaterials[frameMaterialName] || placeholderMaterialforFrames, [testFrameMaterial, frameMaterialName]);
1122
- const gasketMaterial = react.useMemo(() => availableMaterials[testGasketMaterial] || availableMaterials[gasketMaterialName] || new THREE__namespace.MeshStandardMaterial({
1357
+ const doorMaterial = React.useMemo(() => availableMaterials[testDoorMaterial] || availableMaterials[doorMaterialName] || placeholderMaterial, [testDoorMaterial, doorMaterialName]);
1358
+ const frameMaterial = React.useMemo(() => availableMaterials[testFrameMaterial] || availableMaterials[frameMaterialName] || placeholderMaterialforFrames, [testFrameMaterial, frameMaterialName]);
1359
+ const gasketMaterial = React.useMemo(() => availableMaterials[testGasketMaterial] || availableMaterials[gasketMaterialName] || new THREE__namespace.MeshStandardMaterial({
1123
1360
  color: "#111111"
1124
1361
  }), [testGasketMaterial, gasketMaterialName]);
1125
- const doorStopMaterial = react.useMemo(() => {
1362
+ const doorStopMaterial = React.useMemo(() => {
1126
1363
  return availableMaterials[testDoorStopMaterial] || availableMaterials[doorStopMaterialName || ""] || frameMaterial;
1127
1364
  }, [testDoorStopMaterial, doorStopMaterialName, frameType, frameMaterial]);
1128
- const interiorFanlightMaterial = react.useMemo(() => availableMaterials[testInteriorFanlightMaterial] || availableMaterials[interiorFanlightMaterialName] || placeholderMaterial, [testInteriorFanlightMaterial, interiorFanlightMaterialName]);
1129
- const exteriorFanlightMaterial = react.useMemo(() => availableMaterials[testExteriorFanlightMaterial] || availableMaterials[exteriorFanlightMaterialName] || placeholderMaterial, [testExteriorFanlightMaterial, exteriorFanlightMaterialName]);
1130
- const occulusInfillMaterial = react.useMemo(() => availableMaterials[testOcculusInfillMaterial] || availableMaterials[occulusInfillMaterialName] || placeholderMaterial, [testOcculusInfillMaterial, occulusInfillMaterialName]);
1131
- const glassInfillMaterial = react.useMemo(() => availableMaterials[testGlassInfillMaterial] || availableMaterials[glassInfillMaterialName] || placeholderMaterial, [testGlassInfillMaterial, glassInfillMaterialName]);
1132
- const hingeBodyMaterial = react.useMemo(() => availableMaterials[testHingeMaterial] || availableMaterials[hingeMaterialName] || new THREE__namespace.MeshStandardMaterial({
1365
+ const interiorFanlightMaterial = React.useMemo(() => availableMaterials[testInteriorFanlightMaterial] || availableMaterials[interiorFanlightMaterialName] || placeholderMaterial, [testInteriorFanlightMaterial, interiorFanlightMaterialName]);
1366
+ const exteriorFanlightMaterial = React.useMemo(() => availableMaterials[testExteriorFanlightMaterial] || availableMaterials[exteriorFanlightMaterialName] || placeholderMaterial, [testExteriorFanlightMaterial, exteriorFanlightMaterialName]);
1367
+ const occulusInfillMaterial = React.useMemo(() => availableMaterials[testOcculusInfillMaterial] || availableMaterials[occulusInfillMaterialName] || placeholderMaterial, [testOcculusInfillMaterial, occulusInfillMaterialName]);
1368
+ const glassInfillMaterial = React.useMemo(() => availableMaterials[testGlassInfillMaterial] || availableMaterials[glassInfillMaterialName] || placeholderMaterial, [testGlassInfillMaterial, glassInfillMaterialName]);
1369
+ const hingeBodyMaterial = React.useMemo(() => availableMaterials[testHingeMaterial] || availableMaterials[hingeMaterialName] || new THREE__namespace.MeshStandardMaterial({
1133
1370
  color: "#d4d4d4",
1134
1371
  metalness: 1.0,
1135
1372
  roughness: 0.4
1136
1373
  }), [testHingeMaterial, hingeMaterialName]);
1137
- const frontCoverPanelMaterial = react.useMemo(() => availableMaterials[testFrontCoverPanelMaterial] || availableMaterials[frontCoverPanelMaterialName] || placeholderMaterial, [testFrontCoverPanelMaterial, frontCoverPanelMaterialName]);
1138
- const backCoverPanelMaterial = react.useMemo(() => availableMaterials[testBackCoverPanelMaterial] || availableMaterials[backCoverPanelMaterialName] || placeholderMaterial, [testBackCoverPanelMaterial, backCoverPanelMaterialName]);
1139
- const hingeAccentMaterial = react.useMemo(() => new THREE__namespace.MeshStandardMaterial({
1374
+ const frontCoverPanelMaterial = React.useMemo(() => availableMaterials[testFrontCoverPanelMaterial] || availableMaterials[frontCoverPanelMaterialName] || placeholderMaterial, [testFrontCoverPanelMaterial, frontCoverPanelMaterialName]);
1375
+ const backCoverPanelMaterial = React.useMemo(() => availableMaterials[testBackCoverPanelMaterial] || availableMaterials[backCoverPanelMaterialName] || placeholderMaterial, [testBackCoverPanelMaterial, backCoverPanelMaterialName]);
1376
+ const hingeAccentMaterial = React.useMemo(() => new THREE__namespace.MeshStandardMaterial({
1140
1377
  color: "#1a1a1a",
1141
1378
  roughness: 0.1
1142
1379
  }), []);
@@ -1221,8 +1458,8 @@ function DoorModels(_ref6) {
1221
1458
  const notchWidthM = notchWidthValue / 1000;
1222
1459
  const notchDepthM = notchDepthValue / 1000;
1223
1460
  const isOpeningIn = doorOpening === "in";
1224
- const doorStopPositionZ = react.useMemo(() => isOpeningIn ? frameDepthM / 2 - doorStopOffsetFromEdgeM - doorStopDepthM / 2 : -frameDepthM / 2 + doorStopOffsetFromEdgeM + doorStopDepthM / 2, [isOpeningIn, frameDepthM, doorStopOffsetFromEdgeM, doorStopDepthM]);
1225
- const gasketZPosition = react.useMemo(() => isOpeningIn ? doorStopPositionZ - doorStopDepthM / 2 - gasketDepthM / 2 : doorStopPositionZ + doorStopDepthM / 2 + gasketDepthM / 2, [isOpeningIn, doorStopPositionZ, doorStopDepthM, gasketDepthM]);
1461
+ const doorStopPositionZ = React.useMemo(() => isOpeningIn ? frameDepthM / 2 - doorStopOffsetFromEdgeM - doorStopDepthM / 2 : -frameDepthM / 2 + doorStopOffsetFromEdgeM + doorStopDepthM / 2, [isOpeningIn, frameDepthM, doorStopOffsetFromEdgeM, doorStopDepthM]);
1462
+ const gasketZPosition = React.useMemo(() => isOpeningIn ? doorStopPositionZ - doorStopDepthM / 2 - gasketDepthM / 2 : doorStopPositionZ + doorStopDepthM / 2 + gasketDepthM / 2, [isOpeningIn, doorStopPositionZ, doorStopDepthM, gasketDepthM]);
1226
1463
  const secondDoorStopWidthM = secondDoorStopWidth / 1000;
1227
1464
  const secondDoorStopDepthM = secondDoorStopDepth / 1000;
1228
1465
  const secondDoorStopPositionZ = isOpeningIn ? frameDepthM / 2 - secondDoorStopDepthM / 2 : -frameDepthM / 2 + secondDoorStopDepthM / 2;
@@ -1230,7 +1467,7 @@ function DoorModels(_ref6) {
1230
1467
  // Position the first glass panel against the primary doorstop
1231
1468
 
1232
1469
  const secondGasketZPosition = isOpeningIn ? secondDoorStopPositionZ - secondDoorStopDepthM / 2 - gasketDepthM / 2 : secondDoorStopPositionZ + secondDoorStopDepthM / 2 + gasketDepthM / 2;
1233
- const doorCenterZ = react.useMemo(() => {
1470
+ const doorCenterZ = React.useMemo(() => {
1234
1471
  if (frameType === "WF_FLI") {
1235
1472
  if (isOpeningIn) {
1236
1473
  return frameDepthM / 2 - doorDepthM / 2;
@@ -1259,12 +1496,12 @@ function DoorModels(_ref6) {
1259
1496
  const occulusHeightM = mainDoorHeightM - occulusY1M - occulusY2M;
1260
1497
  const occulusPositionXM = (occulusX1M - occulusX2M) / 2;
1261
1498
  const occulusPositionYM = (occulusY2M - occulusY1M) / 2;
1262
- const [isOpen, setIsOpen] = react.useState(false);
1499
+ const [isOpen, setIsOpen] = React.useState(false);
1263
1500
  const hingeSideX = doorPivot === "left" ? -doorWidthM / 2 : doorWidthM / 2;
1264
1501
  const leftGlass_Z = -frameDepthM / 2 + GlassPanelDepthM / 2 - GlassPanelDepthM;
1265
1502
  const rightGlass_Z = frameDepthM / 2 - GlassPanelDepthM / 2 + GlassPanelDepthM;
1266
1503
  // --- PIVOT ---
1267
- const hingeZ = react.useMemo(() => {
1504
+ const hingeZ = React.useMemo(() => {
1268
1505
  if (frameType === "WF_FLI") {
1269
1506
  if (isOpeningIn) {
1270
1507
  return doorCenterZ - doorDepthM / 2;
@@ -1274,7 +1511,7 @@ function DoorModels(_ref6) {
1274
1511
  }
1275
1512
  return isOpeningIn ? -frameDepthM / 2 : frameDepthM / 2;
1276
1513
  }, [frameType, isOpeningIn, doorCenterZ, doorDepthM, frameDepthM]);
1277
- const doorOffsetZ = react.useMemo(() => doorCenterZ - hingeZ, [doorCenterZ, hingeZ]);
1514
+ const doorOffsetZ = React.useMemo(() => doorCenterZ - hingeZ, [doorCenterZ, hingeZ]);
1278
1515
  const directionMultiplier = doorOpening === "in" ? 1 : -1;
1279
1516
  const {
1280
1517
  rotation
@@ -1312,10 +1549,21 @@ function DoorModels(_ref6) {
1312
1549
  const handleCenterYFromDoorBottom = 1.0; // 1000 mm from bottom by default
1313
1550
  const safeHandleY = Math.min(Math.max(handleCenterYFromDoorBottom, 0.25), mainDoorHeightM - 0.25);
1314
1551
  const handleHeightM = -mainDoorHeightM / 2 + safeHandleY; // convert to door local Y
1315
- const latchMarginM = 0.08; // 80 mm from latch edge
1316
- const nonHingeSideX = doorPivot === "left" ? doorWidthM / 2 : -doorWidthM / 2;
1317
- const handleX = nonHingeSideX + (doorPivot === "left" ? -latchMarginM : latchMarginM);
1318
1552
 
1553
+ // Check if the door is a glass type to adjust handle positioning
1554
+ const isSingleGlass = ["SG8", "SG10", "SG12"].includes(bodyType);
1555
+ const nonHingeSideX = doorPivot === "left" ? doorWidthM / 2 : -doorWidthM / 2;
1556
+ let handleX;
1557
+ if (isSingleGlass) {
1558
+ // For the glass handle, position it right at the edge.
1559
+ // The MergedPlate in GlassHandle is 0.1m wide, so we offset by half its width (0.05m).
1560
+ const plateHalfWidth = 0.05;
1561
+ handleX = nonHingeSideX + (doorPivot === "left" ? -plateHalfWidth : plateHalfWidth);
1562
+ } else {
1563
+ // For standard handles, keep the original margin.
1564
+ const latchMarginM = 0.08; // 80 mm from latch edge
1565
+ handleX = nonHingeSideX + (doorPivot === "left" ? -latchMarginM : latchMarginM);
1566
+ }
1319
1567
  // --- Primary Gasket Edge Position Calculations ---
1320
1568
  const topGasketYPosition = totalOpeningHeightM / 2 - doorStopWidthM + gasketWidthM / 2;
1321
1569
  const leftGasketXPosition = -doorWidthM / 2 + doorStopWidthM - gasketWidthM / 2;
@@ -1334,10 +1582,10 @@ function DoorModels(_ref6) {
1334
1582
  const barrelPartHeight = (hingeTotalHeightM - capHeightM * 2 - separatorHeightM) / 2;
1335
1583
 
1336
1584
  // --- HINGE VISIBILITY LOGIC ---
1337
- const isGlassDoor = react.useMemo(() => ["SG8", "SG10", "SG12"].includes(bodyType), [bodyType]);
1585
+ const isGlassDoor = React.useMemo(() => ["SG8", "SG10", "SG12"].includes(bodyType), [bodyType]);
1338
1586
 
1339
1587
  // Calculate evenly spaced hinge positions
1340
- const standardHingeYPositions = react.useMemo(() => {
1588
+ const standardHingeYPositions = React.useMemo(() => {
1341
1589
  const numHinges = 4;
1342
1590
  const topMargin = 180 / 1000;
1343
1591
  const bottomMargin = 180 / 1000;
@@ -1351,7 +1599,7 @@ function DoorModels(_ref6) {
1351
1599
  }, [mainDoorHeightM]);
1352
1600
 
1353
1601
  // Y positions for the new glass hinges
1354
- const glassHingeYPositions = react.useMemo(() => {
1602
+ const glassHingeYPositions = React.useMemo(() => {
1355
1603
  const topMargin = 250 / 1000;
1356
1604
  const secondTopMargin = 450 / 1000;
1357
1605
  const bottomMargin = 250 / 1000;
@@ -1360,7 +1608,7 @@ function DoorModels(_ref6) {
1360
1608
  const bottom = -mainDoorHeightM / 2 + bottomMargin;
1361
1609
  return [top, secondTop, bottom];
1362
1610
  }, [mainDoorHeightM]);
1363
- const isStandardHingeVisible = react.useMemo(() => {
1611
+ const isStandardHingeVisible = React.useMemo(() => {
1364
1612
  if (isGlassDoor) return false;
1365
1613
  if (!isFrameVisible) return false;
1366
1614
  const invisibleFrameTypes = ["WDGF_WDG100", "WF_100", "WF_FLI"];