door_models 5.0.2 → 5.0.4

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":
@@ -618,7 +621,7 @@ const ConfiguratorProvider = _ref => {
618
621
  break;
619
622
  }
620
623
  }, [exteriorFanlight.visible, exteriorFanlightType, doorFrame.frameDepth, setTestExteriorFanlightMaterial, setExteriorFanlight]);
621
- react.useEffect(() => {
624
+ React.useEffect(() => {
622
625
  const topThkValue = parseInt(doorFrame.topThk) || 0;
623
626
  const exteriorFanlightHeight = exteriorFanlight.visible ? exteriorFanlight.height : 0;
624
627
  const newDoorHeight = totalHeight - topThkValue - exteriorFanlightHeight;
@@ -626,7 +629,7 @@ const ConfiguratorProvider = _ref => {
626
629
  doorHeight: newDoorHeight > 0 ? newDoorHeight : 0
627
630
  }));
628
631
  }, [totalHeight, doorFrame.topThk, exteriorFanlight.visible, exteriorFanlight.height]);
629
- react.useEffect(() => {
632
+ React.useEffect(() => {
630
633
  const sidesThkValue = parseInt(doorFrame.sidesThk) || 0;
631
634
  const newDoorWidth = totalWidth - sidesThkValue * 2;
632
635
  setDoor(prevDoor => _objectSpread2(_objectSpread2({}, prevDoor), {}, {
@@ -701,7 +704,7 @@ const ConfiguratorProvider = _ref => {
701
704
  });
702
705
  };
703
706
  const useConfigurator = () => {
704
- const context = react.useContext(ConfiguratorContext);
707
+ const context = React.useContext(ConfiguratorContext);
705
708
  if (!context) {
706
709
  throw new Error("useConfigurator must be used within a ConfiguratorProvider");
707
710
  }
@@ -747,9 +750,22 @@ const availableMaterials = {
747
750
  opacity: 0.7
748
751
  }),
749
752
  aluminum: new THREE__namespace.MeshStandardMaterial({
750
- color: "#dcdcdc",
751
- metalness: 1.0,
752
- roughness: 0.3
753
+ color: "#abb0aa",
754
+ metalness: 0.8,
755
+ roughness: 0.5,
756
+ envMapIntensity: 1.2
757
+ }),
758
+ aluminumBrighter: new THREE__namespace.MeshStandardMaterial({
759
+ color: "#cdcdcd",
760
+ metalness: 0.8,
761
+ roughness: 0.5,
762
+ envMapIntensity: 1.2
763
+ }),
764
+ aluminumExtraBrighter: new THREE__namespace.MeshStandardMaterial({
765
+ color: "#ececec",
766
+ metalness: 0.8,
767
+ roughness: 0.5,
768
+ envMapIntensity: 1.2
753
769
  }),
754
770
  silver: new THREE__namespace.MeshStandardMaterial({
755
771
  color: "#c0c0c0",
@@ -770,159 +786,375 @@ const availableMaterials = {
770
786
  envMapIntensity: 1.5
771
787
  })
772
788
  };
789
+
790
+ // Custom hook for door handle calculations
773
791
  function StandardHandle(_ref) {
774
792
  let {
775
793
  position,
776
794
  doorDepthM,
777
- doorPivot
795
+ doorPivot,
796
+ frameType // 👈
778
797
  } = _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;
798
+ // --- Base Dimensions ---
799
+ const roseRadius = 0.025;
800
+
801
+ // --- Thickness ---
802
+ // default 5mm, but 8mm + 1–2mm if WDG frame
803
+ const roseThickness = frameType === "WDGF_WDG100" ? 0.008 + 0.0015 // average: 9.5mm
804
+ : 0.005; // 5mm default
805
+
806
+ const handleRadius = 0.009;
807
+ const handleLength = 0.12;
808
+
809
+ // face offset based on thickness
786
810
  const faceZ = doorDepthM / 2 + roseThickness / 2;
811
+ const connectorLength = handleLength - 0.08;
812
+ const cornerFrontZ = faceZ + roseThickness + connectorLength;
813
+ const cornerBackZ = -faceZ - roseThickness - connectorLength;
814
+ const roseGapY = 0.012;
787
815
  return /*#__PURE__*/jsxRuntime.jsxs("group", {
788
816
  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,
817
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsxs(React__default["default"].Fragment, {
818
+ children: [frameType === "WDGF_WDG100" ?
819
+ /*#__PURE__*/
820
+ // --- Capsule rose ---
821
+ jsxRuntime.jsxs("group", {
822
+ "position-z": z,
823
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
824
+ material: availableMaterials.aluminum,
825
+ castShadow: true,
826
+ receiveShadow: true,
827
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
828
+ args: [roseRadius * 2, roseRadius * 2, roseThickness]
829
+ })
830
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
831
+ "position-y": roseRadius,
832
+ rotation: [Math.PI / 2, Math.PI / 2, 0],
833
+ material: availableMaterials.aluminum,
834
+ castShadow: true,
835
+ receiveShadow: true,
836
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
837
+ args: [roseRadius, roseRadius, roseThickness, 32, 1, false, 0, Math.PI]
838
+ })
839
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
840
+ "position-y": -roseRadius,
841
+ rotation: [-Math.PI / 2, Math.PI / 2, 0],
842
+ material: availableMaterials.aluminum,
843
+ castShadow: true,
844
+ receiveShadow: true,
845
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
846
+ args: [roseRadius, roseRadius, roseThickness, 32, 1, false, 0, Math.PI]
847
+ })
848
+ })]
849
+ }) :
850
+ /*#__PURE__*/
851
+ // --- Round rose ---
852
+ jsxRuntime.jsx("mesh", {
853
+ rotation: [Math.PI / 2, 0, 0],
854
+ "position-z": z,
855
+ material: availableMaterials.aluminum,
804
856
  castShadow: true,
805
857
  receiveShadow: true,
806
- rotation: [Math.PI / 2, 0, 0],
807
858
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
808
- args: [stemRadius, stemRadius, 0.02, 32]
859
+ args: [roseRadius, roseRadius, roseThickness, 48]
809
860
  })
810
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
811
- position: [0.06, 0, doorDepthM / 2],
812
- material: metal,
861
+ }), frameType === "WDGF_WDG100" ? /*#__PURE__*/jsxRuntime.jsxs("group", {
862
+ "position-z": z,
863
+ "position-y": -(0.08 + roseGapY),
864
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
865
+ material: availableMaterials.aluminum,
866
+ castShadow: true,
867
+ receiveShadow: true,
868
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
869
+ args: [(roseRadius - 0.008) * 2, (roseRadius - 0.008) * 2, roseThickness]
870
+ })
871
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
872
+ "position-y": roseRadius - 0.008,
873
+ rotation: [Math.PI / 2, Math.PI / 2, 0],
874
+ material: availableMaterials.aluminum,
875
+ castShadow: true,
876
+ receiveShadow: true,
877
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
878
+ args: [roseRadius - 0.008, roseRadius - 0.008, roseThickness, 32, 1, false, 0, Math.PI]
879
+ })
880
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
881
+ "position-y": -(roseRadius - 0.008),
882
+ rotation: [-Math.PI / 2, Math.PI / 2, 0],
883
+ material: availableMaterials.aluminum,
884
+ castShadow: true,
885
+ receiveShadow: true,
886
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
887
+ args: [roseRadius - 0.008, roseRadius - 0.008, roseThickness, 32, 1, false, 0, Math.PI]
888
+ })
889
+ })]
890
+ }) : /*#__PURE__*/jsxRuntime.jsx("mesh", {
891
+ rotation: [Math.PI / 2, 0, 0],
892
+ "position-z": z,
893
+ "position-y": -(0.08 + roseGapY),
894
+ material: availableMaterials.aluminum,
813
895
  castShadow: true,
814
896
  receiveShadow: true,
815
- rotation: [0, 0, Math.PI / 2],
816
897
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
817
- args: [leverRadius, leverRadius, leverLength, 32]
898
+ args: [roseRadius, roseRadius, roseThickness, 48]
818
899
  })
900
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
901
+ position: [0, -(0.08 + roseGapY),
902
+ // 👈 same Y as small rose
903
+ z + (z > 0 ? roseThickness : -roseThickness) // 👈 accounts for thickness
904
+ ],
905
+ castShadow: true,
906
+ receiveShadow: true,
907
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
908
+ rotation: [Math.PI / 2, 0, 0],
909
+ position: [0, 0.0075, 0],
910
+ material: availableMaterials.aluminumBrighter,
911
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
912
+ args: [0.008, 0.008, roseThickness, 32]
913
+ })
914
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
915
+ position: [0, -0.0075, 0],
916
+ material: availableMaterials.aluminumBrighter,
917
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
918
+ args: [0.008, 0.015, roseThickness]
919
+ })
920
+ })]
921
+ })]
922
+ }, i)), /*#__PURE__*/jsxRuntime.jsxs("group", {
923
+ scale: [doorPivot === "left" ? -1 : 1, 1, 1],
924
+ children: [/*#__PURE__*/jsxRuntime.jsxs("group", {
925
+ position: [0, 0, -0.01],
926
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
927
+ position: [0, 0, faceZ + roseThickness + connectorLength / 2],
928
+ rotation: [Math.PI / 2, 0, 0],
929
+ castShadow: true,
930
+ receiveShadow: true,
931
+ material: availableMaterials.aluminum,
932
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
933
+ args: [handleRadius, handleRadius, connectorLength, 48]
934
+ })
935
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
936
+ position: [0, 0, cornerFrontZ],
937
+ castShadow: true,
938
+ receiveShadow: true,
939
+ material: availableMaterials.aluminum,
940
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
941
+ args: [handleRadius, 32, 32]
942
+ })
943
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
944
+ position: [handleLength / 2, 0, cornerFrontZ],
945
+ rotation: [0, 0, Math.PI / 2],
946
+ castShadow: true,
947
+ receiveShadow: true,
948
+ material: availableMaterials.aluminum,
949
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
950
+ args: [handleRadius, handleRadius, handleLength, 48]
951
+ })
952
+ })]
953
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
954
+ position: [0, 0, 0.01],
955
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
956
+ position: [0, 0, -faceZ - roseThickness - connectorLength / 2],
957
+ rotation: [Math.PI / 2, 0, 0],
958
+ castShadow: true,
959
+ receiveShadow: true,
960
+ material: availableMaterials.aluminum,
961
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
962
+ args: [handleRadius, handleRadius, connectorLength, 48]
963
+ })
964
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
965
+ position: [0, 0, cornerBackZ],
966
+ castShadow: true,
967
+ receiveShadow: true,
968
+ material: availableMaterials.aluminum,
969
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
970
+ args: [handleRadius, 32, 32]
971
+ })
972
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
973
+ position: [handleLength / 2, 0, cornerBackZ],
974
+ rotation: [0, 0, Math.PI / 2],
975
+ castShadow: true,
976
+ receiveShadow: true,
977
+ material: availableMaterials.aluminum,
978
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
979
+ args: [handleRadius, handleRadius, handleLength, 48]
980
+ })
981
+ })]
819
982
  })]
820
983
  })]
821
984
  });
822
985
  }
823
- function GlassHandle(_ref2) {
986
+ const MergedPlate = _ref2 => {
987
+ let {
988
+ plateMaterial,
989
+ roseThickness,
990
+ faceZ
991
+ } = _ref2;
992
+ const geometry = React.useMemo(() => {
993
+ // Left half - sharp edges
994
+ const leftHalf = new THREE__namespace.BoxGeometry(0.05, 0.24, roseThickness);
995
+ leftHalf.translate(-0.025, 0, 0); // Center the left half
996
+
997
+ const shape = new THREE__namespace.Shape();
998
+ const width = 0.1;
999
+ const height = 0.24;
1000
+ const radius = 0.01;
1001
+ shape.moveTo(-width / 2, -height / 2);
1002
+ shape.lineTo(-width / 2, height / 2);
1003
+ shape.lineTo(width / 2 - radius, height / 2);
1004
+ shape.absarc(width / 2 - radius, height / 2 - radius, radius, Math.PI / 2, 0, true);
1005
+ shape.lineTo(width / 2, -height / 2 + radius);
1006
+ shape.absarc(width / 2 - radius, -height / 2 + radius, radius, 0, -Math.PI / 2, true);
1007
+ shape.lineTo(-width / 2, -height / 2);
1008
+ const extrudeSettings = {
1009
+ steps: 2,
1010
+ depth: roseThickness,
1011
+ bevelEnabled: false
1012
+ };
1013
+ return new THREE__namespace.ExtrudeGeometry(shape, extrudeSettings);
1014
+ }, [roseThickness]);
1015
+ return /*#__PURE__*/jsxRuntime.jsx("group", {
1016
+ "position-z": faceZ,
1017
+ children: /*#__PURE__*/jsxRuntime.jsx("mesh", {
1018
+ geometry: geometry,
1019
+ material: plateMaterial,
1020
+ castShadow: true,
1021
+ receiveShadow: true
1022
+ })
1023
+ });
1024
+ };
1025
+ function GlassHandle(_ref3) {
824
1026
  let {
825
1027
  position,
826
1028
  doorDepthM,
827
1029
  doorPivot
828
- } = _ref2;
829
- // --- Dimensions and materials ---
1030
+ } = _ref3;
1031
+ // --- Dimensions ---
830
1032
  const roseRadius = 0.025;
831
1033
  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;
1034
+ const handleRadius = 0.009;
1035
+ const handleLength = 0.12;
838
1036
  const faceZ = doorDepthM / 2 + roseThickness / 2;
1037
+ const connectorLength = handleLength - 0.08;
839
1038
  return /*#__PURE__*/jsxRuntime.jsxs("group", {
840
1039
  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,
1040
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsxs(React__default["default"].Fragment, {
868
1041
  children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
869
- "position-z": doorDepthM / 2 + bendRadius,
870
- material: metal,
871
- castShadow: true,
872
- receiveShadow: true,
873
1042
  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,
1043
+ "position-z": z + (z > 0 ? roseThickness : -roseThickness) + 0.002,
1044
+ material: availableMaterials.aluminum,
880
1045
  castShadow: true,
881
1046
  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
1047
  children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
892
- args: [leverRadius, leverRadius * 0.8, leverLength, 32]
1048
+ args: [roseRadius, roseRadius, roseThickness, 48]
893
1049
  })
894
- }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
895
- position: [bendRadius + leverLength, 0, doorDepthM / 2],
896
- material: metal,
1050
+ }), /*#__PURE__*/jsxRuntime.jsxs("mesh", {
1051
+ position: [0, -0.08, z + (z > 0 ? roseThickness : -roseThickness)],
897
1052
  castShadow: true,
898
- children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
899
- args: [leverRadius * 0.8, 12, 12]
900
- })
1053
+ receiveShadow: true,
1054
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1055
+ rotation: [Math.PI / 2, 0, 0],
1056
+ position: [0, 0.0075, 0],
1057
+ material: availableMaterials.aluminum,
1058
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1059
+ args: [0.008, 0.008, roseThickness, 32]
1060
+ })
1061
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1062
+ position: [0, -0.0075, 0],
1063
+ material: availableMaterials.aluminum,
1064
+ children: /*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
1065
+ args: [0.008, 0.015, roseThickness]
1066
+ })
1067
+ })]
1068
+ })]
1069
+ }, i)), /*#__PURE__*/jsxRuntime.jsxs("group", {
1070
+ "scale-x": doorPivot === "left" ? -1 : 1,
1071
+ children: [[faceZ, -faceZ].map((z, i) => /*#__PURE__*/jsxRuntime.jsx(MergedPlate, {
1072
+ faceZ: z,
1073
+ plateMaterial: availableMaterials.aluminumExtraBrighter,
1074
+ roseThickness: roseThickness
1075
+ }, "plate-".concat(i))), /*#__PURE__*/jsxRuntime.jsxs("group", {
1076
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1077
+ position: [handleLength / 2, 0, faceZ + connectorLength],
1078
+ rotation: [0, 0, Math.PI / 2],
1079
+ material: availableMaterials.aluminum,
1080
+ castShadow: true,
1081
+ receiveShadow: true,
1082
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1083
+ args: [handleRadius, handleRadius, handleLength, 48]
1084
+ })
1085
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1086
+ position: [0, 0, faceZ + connectorLength / 2],
1087
+ rotation: [Math.PI / 2, 0, 0],
1088
+ material: availableMaterials.aluminum,
1089
+ castShadow: true,
1090
+ receiveShadow: true,
1091
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1092
+ args: [handleRadius, handleRadius, connectorLength, 48]
1093
+ })
1094
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1095
+ position: [0, 0, faceZ + connectorLength],
1096
+ material: availableMaterials.aluminum,
1097
+ castShadow: true,
1098
+ receiveShadow: true,
1099
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
1100
+ args: [handleRadius, 32, 32]
1101
+ })
1102
+ })]
1103
+ }), /*#__PURE__*/jsxRuntime.jsxs("group", {
1104
+ children: [/*#__PURE__*/jsxRuntime.jsx("mesh", {
1105
+ position: [handleLength / 2, 0, -(faceZ + connectorLength)],
1106
+ rotation: [0, 0, Math.PI / 2],
1107
+ material: availableMaterials.aluminum,
1108
+ castShadow: true,
1109
+ receiveShadow: true,
1110
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1111
+ args: [handleRadius, handleRadius, handleLength, 48]
1112
+ })
1113
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1114
+ position: [0, 0, -(faceZ + connectorLength / 2)],
1115
+ rotation: [Math.PI / 2, 0, 0],
1116
+ material: availableMaterials.aluminum,
1117
+ castShadow: true,
1118
+ receiveShadow: true,
1119
+ children: /*#__PURE__*/jsxRuntime.jsx("cylinderGeometry", {
1120
+ args: [handleRadius, handleRadius, connectorLength, 48]
1121
+ })
1122
+ }), /*#__PURE__*/jsxRuntime.jsx("mesh", {
1123
+ position: [0, 0, -(faceZ + connectorLength)],
1124
+ material: availableMaterials.aluminum,
1125
+ castShadow: true,
1126
+ receiveShadow: true,
1127
+ children: /*#__PURE__*/jsxRuntime.jsx("sphereGeometry", {
1128
+ args: [handleRadius, 32, 32]
1129
+ })
1130
+ })]
901
1131
  })]
902
1132
  })]
903
1133
  });
904
1134
  }
905
- function DoorHandle(_ref3) {
1135
+ function DoorHandle(_ref4) {
906
1136
  let {
907
1137
  bodyType,
908
1138
  handleX,
909
1139
  handleHeightM,
910
1140
  doorDepthM,
911
1141
  doorPivot
912
- } = _ref3;
1142
+ } = _ref4;
913
1143
  const isSingleGlass = ["SG8", "SG10", "SG12"].includes(bodyType);
914
1144
  const handlePos = [handleX, handleHeightM, 0];
1145
+ const frameType = useConfigurator().frameType;
915
1146
  return isSingleGlass ? /*#__PURE__*/jsxRuntime.jsx(GlassHandle, {
916
- position: handlePos,
1147
+ position: [handleX, handleHeightM, -0.0024],
917
1148
  doorDepthM: doorDepthM,
918
1149
  doorPivot: doorPivot
919
1150
  }) : /*#__PURE__*/jsxRuntime.jsx(StandardHandle, {
920
1151
  position: handlePos,
921
1152
  doorDepthM: doorDepthM,
922
- doorPivot: doorPivot
1153
+ doorPivot: doorPivot,
1154
+ frameType: frameType
923
1155
  });
924
1156
  }
925
- function GlassHinge(_ref4) {
1157
+ function GlassHinge(_ref5) {
926
1158
  let {
927
1159
  position,
928
1160
  pivot,
@@ -930,7 +1162,7 @@ function GlassHinge(_ref4) {
930
1162
  doorDepthM,
931
1163
  material,
932
1164
  gasketMaterial
933
- } = _ref4;
1165
+ } = _ref5;
934
1166
  const plateWidth = 130 / 1000;
935
1167
  const plateHeight = 55 / 1000;
936
1168
  const plateThickness = 8 / 1000;
@@ -1006,7 +1238,7 @@ function GlassHinge(_ref4) {
1006
1238
  })]
1007
1239
  });
1008
1240
  }
1009
- function DoorStopCuts(_ref5) {
1241
+ function DoorStopCuts(_ref6) {
1010
1242
  let {
1011
1243
  visible,
1012
1244
  width,
@@ -1018,7 +1250,7 @@ function DoorStopCuts(_ref5) {
1018
1250
  glassDepthOffset = 0,
1019
1251
  material,
1020
1252
  setName
1021
- } = _ref5;
1253
+ } = _ref6;
1022
1254
  if (!visible) return null;
1023
1255
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1024
1256
  children: [/*#__PURE__*/jsxRuntime.jsx(csg.Subtraction, {
@@ -1045,10 +1277,10 @@ function DoorStopCuts(_ref5) {
1045
1277
  })]
1046
1278
  });
1047
1279
  }
1048
- function DoorModels(_ref6) {
1280
+ function DoorModels(_ref7) {
1049
1281
  let {
1050
1282
  doorName
1051
- } = _ref6;
1283
+ } = _ref7;
1052
1284
  const {
1053
1285
  is2D,
1054
1286
  totalWidth,
@@ -1081,7 +1313,7 @@ function DoorModels(_ref6) {
1081
1313
  glassDepth,
1082
1314
  handleParseCpid
1083
1315
  } = useConfigurator();
1084
- react.useEffect(() => {
1316
+ React.useEffect(() => {
1085
1317
  if (doorName) {
1086
1318
  handleParseCpid(doorName);
1087
1319
  }
@@ -1117,26 +1349,26 @@ function DoorModels(_ref6) {
1117
1349
  } = backCoverPanel;
1118
1350
 
1119
1351
  // --- 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({
1352
+ const doorMaterial = React.useMemo(() => availableMaterials[testDoorMaterial] || availableMaterials[doorMaterialName] || placeholderMaterial, [testDoorMaterial, doorMaterialName]);
1353
+ const frameMaterial = React.useMemo(() => availableMaterials[testFrameMaterial] || availableMaterials[frameMaterialName] || placeholderMaterialforFrames, [testFrameMaterial, frameMaterialName]);
1354
+ const gasketMaterial = React.useMemo(() => availableMaterials[testGasketMaterial] || availableMaterials[gasketMaterialName] || new THREE__namespace.MeshStandardMaterial({
1123
1355
  color: "#111111"
1124
1356
  }), [testGasketMaterial, gasketMaterialName]);
1125
- const doorStopMaterial = react.useMemo(() => {
1357
+ const doorStopMaterial = React.useMemo(() => {
1126
1358
  return availableMaterials[testDoorStopMaterial] || availableMaterials[doorStopMaterialName || ""] || frameMaterial;
1127
1359
  }, [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({
1360
+ const interiorFanlightMaterial = React.useMemo(() => availableMaterials[testInteriorFanlightMaterial] || availableMaterials[interiorFanlightMaterialName] || placeholderMaterial, [testInteriorFanlightMaterial, interiorFanlightMaterialName]);
1361
+ const exteriorFanlightMaterial = React.useMemo(() => availableMaterials[testExteriorFanlightMaterial] || availableMaterials[exteriorFanlightMaterialName] || placeholderMaterial, [testExteriorFanlightMaterial, exteriorFanlightMaterialName]);
1362
+ const occulusInfillMaterial = React.useMemo(() => availableMaterials[testOcculusInfillMaterial] || availableMaterials[occulusInfillMaterialName] || placeholderMaterial, [testOcculusInfillMaterial, occulusInfillMaterialName]);
1363
+ const glassInfillMaterial = React.useMemo(() => availableMaterials[testGlassInfillMaterial] || availableMaterials[glassInfillMaterialName] || placeholderMaterial, [testGlassInfillMaterial, glassInfillMaterialName]);
1364
+ const hingeBodyMaterial = React.useMemo(() => availableMaterials[testHingeMaterial] || availableMaterials[hingeMaterialName] || new THREE__namespace.MeshStandardMaterial({
1133
1365
  color: "#d4d4d4",
1134
1366
  metalness: 1.0,
1135
1367
  roughness: 0.4
1136
1368
  }), [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({
1369
+ const frontCoverPanelMaterial = React.useMemo(() => availableMaterials[testFrontCoverPanelMaterial] || availableMaterials[frontCoverPanelMaterialName] || placeholderMaterial, [testFrontCoverPanelMaterial, frontCoverPanelMaterialName]);
1370
+ const backCoverPanelMaterial = React.useMemo(() => availableMaterials[testBackCoverPanelMaterial] || availableMaterials[backCoverPanelMaterialName] || placeholderMaterial, [testBackCoverPanelMaterial, backCoverPanelMaterialName]);
1371
+ const hingeAccentMaterial = React.useMemo(() => new THREE__namespace.MeshStandardMaterial({
1140
1372
  color: "#1a1a1a",
1141
1373
  roughness: 0.1
1142
1374
  }), []);
@@ -1221,8 +1453,8 @@ function DoorModels(_ref6) {
1221
1453
  const notchWidthM = notchWidthValue / 1000;
1222
1454
  const notchDepthM = notchDepthValue / 1000;
1223
1455
  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]);
1456
+ const doorStopPositionZ = React.useMemo(() => isOpeningIn ? frameDepthM / 2 - doorStopOffsetFromEdgeM - doorStopDepthM / 2 : -frameDepthM / 2 + doorStopOffsetFromEdgeM + doorStopDepthM / 2, [isOpeningIn, frameDepthM, doorStopOffsetFromEdgeM, doorStopDepthM]);
1457
+ const gasketZPosition = React.useMemo(() => isOpeningIn ? doorStopPositionZ - doorStopDepthM / 2 - gasketDepthM / 2 : doorStopPositionZ + doorStopDepthM / 2 + gasketDepthM / 2, [isOpeningIn, doorStopPositionZ, doorStopDepthM, gasketDepthM]);
1226
1458
  const secondDoorStopWidthM = secondDoorStopWidth / 1000;
1227
1459
  const secondDoorStopDepthM = secondDoorStopDepth / 1000;
1228
1460
  const secondDoorStopPositionZ = isOpeningIn ? frameDepthM / 2 - secondDoorStopDepthM / 2 : -frameDepthM / 2 + secondDoorStopDepthM / 2;
@@ -1230,7 +1462,7 @@ function DoorModels(_ref6) {
1230
1462
  // Position the first glass panel against the primary doorstop
1231
1463
 
1232
1464
  const secondGasketZPosition = isOpeningIn ? secondDoorStopPositionZ - secondDoorStopDepthM / 2 - gasketDepthM / 2 : secondDoorStopPositionZ + secondDoorStopDepthM / 2 + gasketDepthM / 2;
1233
- const doorCenterZ = react.useMemo(() => {
1465
+ const doorCenterZ = React.useMemo(() => {
1234
1466
  if (frameType === "WF_FLI") {
1235
1467
  if (isOpeningIn) {
1236
1468
  return frameDepthM / 2 - doorDepthM / 2;
@@ -1259,12 +1491,12 @@ function DoorModels(_ref6) {
1259
1491
  const occulusHeightM = mainDoorHeightM - occulusY1M - occulusY2M;
1260
1492
  const occulusPositionXM = (occulusX1M - occulusX2M) / 2;
1261
1493
  const occulusPositionYM = (occulusY2M - occulusY1M) / 2;
1262
- const [isOpen, setIsOpen] = react.useState(false);
1494
+ const [isOpen, setIsOpen] = React.useState(false);
1263
1495
  const hingeSideX = doorPivot === "left" ? -doorWidthM / 2 : doorWidthM / 2;
1264
1496
  const leftGlass_Z = -frameDepthM / 2 + GlassPanelDepthM / 2 - GlassPanelDepthM;
1265
1497
  const rightGlass_Z = frameDepthM / 2 - GlassPanelDepthM / 2 + GlassPanelDepthM;
1266
1498
  // --- PIVOT ---
1267
- const hingeZ = react.useMemo(() => {
1499
+ const hingeZ = React.useMemo(() => {
1268
1500
  if (frameType === "WF_FLI") {
1269
1501
  if (isOpeningIn) {
1270
1502
  return doorCenterZ - doorDepthM / 2;
@@ -1274,7 +1506,7 @@ function DoorModels(_ref6) {
1274
1506
  }
1275
1507
  return isOpeningIn ? -frameDepthM / 2 : frameDepthM / 2;
1276
1508
  }, [frameType, isOpeningIn, doorCenterZ, doorDepthM, frameDepthM]);
1277
- const doorOffsetZ = react.useMemo(() => doorCenterZ - hingeZ, [doorCenterZ, hingeZ]);
1509
+ const doorOffsetZ = React.useMemo(() => doorCenterZ - hingeZ, [doorCenterZ, hingeZ]);
1278
1510
  const directionMultiplier = doorOpening === "in" ? 1 : -1;
1279
1511
  const {
1280
1512
  rotation
@@ -1312,10 +1544,21 @@ function DoorModels(_ref6) {
1312
1544
  const handleCenterYFromDoorBottom = 1.0; // 1000 mm from bottom by default
1313
1545
  const safeHandleY = Math.min(Math.max(handleCenterYFromDoorBottom, 0.25), mainDoorHeightM - 0.25);
1314
1546
  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
1547
 
1548
+ // Check if the door is a glass type to adjust handle positioning
1549
+ const isSingleGlass = ["SG8", "SG10", "SG12"].includes(bodyType);
1550
+ const nonHingeSideX = doorPivot === "left" ? doorWidthM / 2 : -doorWidthM / 2;
1551
+ let handleX;
1552
+ if (isSingleGlass) {
1553
+ // For the glass handle, position it right at the edge.
1554
+ // The MergedPlate in GlassHandle is 0.1m wide, so we offset by half its width (0.05m).
1555
+ const plateHalfWidth = 0.05;
1556
+ handleX = nonHingeSideX + (doorPivot === "left" ? -plateHalfWidth : plateHalfWidth);
1557
+ } else {
1558
+ // For standard handles, keep the original margin.
1559
+ const latchMarginM = 0.08; // 80 mm from latch edge
1560
+ handleX = nonHingeSideX + (doorPivot === "left" ? -latchMarginM : latchMarginM);
1561
+ }
1319
1562
  // --- Primary Gasket Edge Position Calculations ---
1320
1563
  const topGasketYPosition = totalOpeningHeightM / 2 - doorStopWidthM + gasketWidthM / 2;
1321
1564
  const leftGasketXPosition = -doorWidthM / 2 + doorStopWidthM - gasketWidthM / 2;
@@ -1334,10 +1577,10 @@ function DoorModels(_ref6) {
1334
1577
  const barrelPartHeight = (hingeTotalHeightM - capHeightM * 2 - separatorHeightM) / 2;
1335
1578
 
1336
1579
  // --- HINGE VISIBILITY LOGIC ---
1337
- const isGlassDoor = react.useMemo(() => ["SG8", "SG10", "SG12"].includes(bodyType), [bodyType]);
1580
+ const isGlassDoor = React.useMemo(() => ["SG8", "SG10", "SG12"].includes(bodyType), [bodyType]);
1338
1581
 
1339
1582
  // Calculate evenly spaced hinge positions
1340
- const standardHingeYPositions = react.useMemo(() => {
1583
+ const standardHingeYPositions = React.useMemo(() => {
1341
1584
  const numHinges = 4;
1342
1585
  const topMargin = 180 / 1000;
1343
1586
  const bottomMargin = 180 / 1000;
@@ -1351,7 +1594,7 @@ function DoorModels(_ref6) {
1351
1594
  }, [mainDoorHeightM]);
1352
1595
 
1353
1596
  // Y positions for the new glass hinges
1354
- const glassHingeYPositions = react.useMemo(() => {
1597
+ const glassHingeYPositions = React.useMemo(() => {
1355
1598
  const topMargin = 250 / 1000;
1356
1599
  const secondTopMargin = 450 / 1000;
1357
1600
  const bottomMargin = 250 / 1000;
@@ -1360,7 +1603,7 @@ function DoorModels(_ref6) {
1360
1603
  const bottom = -mainDoorHeightM / 2 + bottomMargin;
1361
1604
  return [top, secondTop, bottom];
1362
1605
  }, [mainDoorHeightM]);
1363
- const isStandardHingeVisible = react.useMemo(() => {
1606
+ const isStandardHingeVisible = React.useMemo(() => {
1364
1607
  if (isGlassDoor) return false;
1365
1608
  if (!isFrameVisible) return false;
1366
1609
  const invisibleFrameTypes = ["WDGF_WDG100", "WF_100", "WF_FLI"];
@@ -1371,7 +1614,7 @@ function DoorModels(_ref6) {
1371
1614
  }, [isFrameVisible, frameType, isGlassDoor]);
1372
1615
  if (is2D) {
1373
1616
  return /*#__PURE__*/jsxRuntime.jsx("group", {
1374
- "position-y": yCenteringOffset + 0.2,
1617
+ "position-y": yCenteringOffset + 0.1,
1375
1618
  children: /*#__PURE__*/jsxRuntime.jsxs("mesh", {
1376
1619
  children: [/*#__PURE__*/jsxRuntime.jsx("boxGeometry", {
1377
1620
  args: [totalWidth / 1000, 0.1, frameDepth / 1000]